OVER के साथ विंडो फ़ंक्शन में DISTINCT का उपयोग करना


18

मैं Oracle से SQL Server 2014 के लिए एक क्वेरी माइग्रेट करने का प्रयास कर रहा हूं।

यहाँ मेरी क्वेरी ओरेकल में बहुत अच्छी है:

select
count(distinct A) over (partition by B) / count(*) over() as A_B
from MyTable 

SQL सर्वर 2014 में इस क्वेरी को चलाने का प्रयास करने के बाद मुझे मिली त्रुटि यहाँ है।

Use of DISTINCT is not allowed with the OVER clause

किसी को पता है कि समस्या क्या है? क्या SQL Server में इस तरह की क्वेरी संभव है? कृपया सलाह दें।


क्या वास्तव में यो को प्रत्येक पंक्ति के लिए परिणाम में एक पंक्ति की आवश्यकता है MyTable? या अलग-अलग पंक्तियाँ पर्याप्त हैं? और अगर आपको पंक्तियों में कोई त्रुटि नहीं है, तो आपको शून्य त्रुटि द्वारा विभाजन पर विचार करने की आवश्यकता नहीं है MyTable?
इरविन ब्रान्डेसटेटर

जवाबों:


12

किसी को पता है कि समस्या क्या है? क्या SQL Server में इस तरह की क्वेरी संभव है?

वर्तमान में यह लागू नहीं है। निम्नलिखित कनेक्ट आइटम अनुरोध देखें।

ओवर क्लॉज एन्हांसमेंट रिक्वेस्ट - एग्रीकल्चर फंक्शन के लिए DISTINCT क्लॉज

एक अन्य संभावित संस्करण होगा

SELECT M.A,
       M.B,
       T.A_B
FROM   MyTable M
       JOIN (SELECT CAST(COUNT(DISTINCT A) AS NUMERIC(18,8)) / SUM(COUNT(*)) OVER() AS A_B,
                    B
             FROM   MyTable
             GROUP  BY B) T
         ON EXISTS (SELECT M.B INTERSECT SELECT T.B) 

NUMERICपूर्णांक विभाजन से बचने के लिए कास्ट है । ज्वाइन क्लॉज का कारण यहां बताया गया है

इसे ON M.B = T.B OR (M.B IS NULL AND T.B IS NULL)यदि पसंद किया जाता है (या बस ON M.B = T.Bयदि Bस्तंभ अशक्त नहीं है) से बदला जा सकता है ।


14

यह B द्वारा विभाजित A के लिए अलग गणना (*) देता है:

dense_rank() over (partition by B order by A) 
+ dense_rank() over (partition by B order by A desc) 
- 1

3
दिलचस्प समाधान। मुझे लगता है कि यह एक डिस्क्लेमर होना चाहिए कि यह तब काम करता है जब Aयह गैर-अशक्त हो (जैसा कि मुझे लगता है कि यह अच्छी तरह से शून्य को गिनता है)।
ypercube y

यह abs(dense_rank - dense_rank) + 1मुझे विश्वास होना चाहिए ।
नोरकल्ली

7

dense_rank()B द्वारा विभाजित A की विशिष्ट गणना प्राप्त करने के लिए आप अधिकतम मूल्य ले सकते हैं ।

मामले की देखभाल करने के लिए जहां ए में शून्य मान हो सकते हैं आप first_valueयह पता लगाने के लिए उपयोग कर सकते हैं कि क्या एक विभाजन में एक अशक्त मौजूद है या नहीं और फिर 1 को घटाएं यदि यह टिप्पणी में मार्टिन स्मिथ द्वारा सुझाया गया है।

select (max(T.DenseRankA) over(partition by T.B) - 
          cast(iif(T.FirstA is null, 1, 0) as numeric(18, 8))) / T.TotalCount as A_B
from (
     select dense_rank() over(partition by T.B order by T.A) DenseRankA,
            first_value(T.A) over(partition by T.B order by T.A) as FirstA,
            count(*) over() as TotalCount,
            T.A,
            T.B
     from MyTable as T
     ) as T

5

ए, बी, और गिनती सहित, एक सबक्वेरी करने की कोशिश करें। तब आपकी बाहरी क्वेरी में, आपकी गिनती (अलग) एक नियमित गिनती बन जाती है, और आपकी गिनती (*) एक योग (cnt) बन जाती है।

select
count(A) over (partition by B) * 1.0 / 
    sum(cnt) over() as A_B
from
(select A, B, count(*) as cnt
 from MyTable
 group by A, B) as partial;
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.