2011-06-02 29 views
136
USE AdventureWorks2008R2; 
GO 
SELECT SalesOrderID, ProductID, OrderQty 
    ,SUM(OrderQty) OVER(PARTITION BY SalesOrderID) AS 'Total' 
    ,AVG(OrderQty) OVER(PARTITION BY SalesOrderID) AS 'Avg' 
    ,COUNT(OrderQty) OVER(PARTITION BY SalesOrderID) AS 'Count' 
    ,MIN(OrderQty) OVER(PARTITION BY SalesOrderID) AS 'Min' 
    ,MAX(OrderQty) OVER(PARTITION BY SalesOrderID) AS 'Max' 
FROM Sales.SalesOrderDetail 
WHERE SalesOrderID IN(43659,43664); 

मैंने उस खंड के बारे में पढ़ा और मुझे समझ में नहीं आया कि मुझे इसकी आवश्यकता क्यों है। फ़ंक्शन Over क्या करता है? Partitioning By क्या करता है? मैं Group By SalesOrderID लिखने के साथ कोई प्रश्न क्यों नहीं बना सकता?एसक्यूएल ओवर() खंड - कब और क्यों उपयोगी है?

+14

कोई फर्क नहीं पड़ता कि आप आरडीबीएमएस का उपयोग करते हैं, [पोस्टग्रेस ट्यूटोरियल] (http://www.postgresql.org/docs/8.4/interactive/tutorial-window.html) सहायक हो सकता है। उदाहरण हैं; मेरी मदद की। –

+0

@AndrewLazarus यह एक शानदार लिंक है –

उत्तर

54

OVER खंड है कि में शक्तिशाली आप विभिन्न श्रेणियों से अधिक समुच्चय हो सकता है ("विंडोइंग") है, चाहे आप एक GROUP BY या नहीं

उदाहरण का उपयोग करें: SalesOrderID और सभी

SELECT 
    SalesOrderID, ProductID, OrderQty 
    ,COUNT(OrderQty) AS 'Count' 
    ,COUNT(*) OVER() AS 'CountAll' 
FROM Sales.SalesOrderDetail 
WHERE 
    SalesOrderID IN(43659,43664) 
GROUP BY 
    SalesOrderID, ProductID, OrderQty 
की गिनती के अनुसार गिनती हो

अलग COUNT रों जाओ, कोई GROUP BY

SELECT 
    SalesOrderID, ProductID, OrderQty 
    ,COUNT(OrderQty) OVER(PARTITION BY SalesOrderID) AS 'CountQtyPerOrder' 
    ,COUNT(OrderQty) OVER(PARTITION BY ProductID) AS 'CountQtyPerProduct', 
    ,COUNT(*) OVER() AS 'CountAllAgain' 
FROM Sales.SalesOrderDetail 
WHERE 
    SalesOrderID IN(43659,43664) 
15

से अधिक खंड whe एन स्थिति के साथ संयुक्त राज्य द्वारा कहा गया है कि पिछले कार्य कॉल को क्वेरी की लौटाई गई पंक्तियों का मूल्यांकन करके विश्लेषणात्मक रूप से किया जाना चाहिए। इसके बारे में एक इनलाइन ग्रुप बाय स्टेटमेंट के रूप में सोचें।

OVER (PARTITION BY SalesOrderID) यह बता रहा है कि एसयूएम, एवीजी, आदि के लिए ... फ़ंक्शन, क्वेरी से लौटाए गए रिकॉर्ड्स के सबसेट पर मूल्य लौटाएं, और पार्टनर जो विदेशी कुंजी SalesOrderID द्वारा सबसेट करता है।

तो हम प्रत्येक अद्वितीय बिक्रीऑर्डर आईडी के लिए प्रत्येक ऑर्डरक्टी रिकॉर्ड को एसयूएम करेंगे, और उस कॉलम नाम को 'कुल' कहा जाएगा।

यह एक ही जानकारी को खोजने के लिए एकाधिक इनलाइन दृश्यों का उपयोग करने से बहुत अधिक प्रभावी माध्यम है। आप इस क्वेरी को इनलाइन व्यू में डाल सकते हैं और फिर कुल पर फ़िल्टर कर सकते हैं।

SELECT ..., 
FROM (your query) inlineview 
WHERE Total < 200 
41

यदि आप केवल SalesOrderID द्वारा समूह चाहता था तो आप SELECT खंड में ProductID और OrderQty स्तंभों में शामिल करने में सक्षम नहीं होगा।

खंड द्वारा भाग आप अपने कुल कार्यों को तोड़ने देते हैं।

SELECT 
    O.order_id, 
    O.order_date, 
    ROW_NUMBER() OVER(PARTITION BY O.order_id) AS line_item_no, 
    OL.product_id 
FROM 
    Orders O 
INNER JOIN Order_Lines OL ON OL.order_id = O.order_id 

(मेरे वाक्य रचना थोड़ा दूर हो सकता है)

फिर आपको वापस की तरह कुछ मिलेगा:

एक स्पष्ट और उपयोगी उदाहरण है अगर आप एक आदेश पर आदेश लाइनों के लिए लाइन नंबर उत्पन्न करने के लिए चाहता था होगा
order_id order_date line_item_no product_id 
-------- ---------- ------------ ---------- 
    1  2011-05-02   1    5 
    1  2011-05-02   2    4 
    1  2011-05-02   3    7 
    2  2011-05-12   1    8 
    2  2011-05-12   2    1 
116

आप GROUP BY SalesOrderID का उपयोग कर सकते हैं। अंतर यह है कि ग्रुप बाय के साथ आपके पास केवल उन कॉलम के लिए समेकित मान हो सकते हैं जो ग्रुप बाय में शामिल नहीं हैं।

इसके विपरीत, ग्रुप बी के बजाए विंडो किए गए कुल कार्यों का उपयोग करके, आप समेकित और गैर-समेकित मान दोनों को पुनर्प्राप्त कर सकते हैं। यही है, यद्यपि आप अपनी उदाहरण क्वेरी में ऐसा नहीं कर रहे हैं, फिर भी आप SalesOrderID एस के समूहों पर व्यक्तिगत OrderQty मान और उनके रकम, गणना, औसत इत्यादि दोनों को पुनर्प्राप्त कर सकते हैं।

यहां एक व्यावहारिक उदाहरण है कि क्यों खिड़की वाले समूह महान हैं। मान लीजिए कि आपको गणना करने की आवश्यकता है कि कुल मूल्य का प्रतिशत क्या है। खिड़की वाले योगों के बिना आपको पहले समेकित मूल्यों की एक सूची प्राप्त करनी होगी और फिर इसे मूल पंक्ति में वापस शामिल करना होगा, यानी।इस तरह:

SELECT 
    orig.[Partition], 
    orig.Value, 
    orig.Value * 100.0/agg.TotalValue AS ValuePercent 
FROM OriginalRowset orig 
    INNER JOIN (
    SELECT 
     [Partition], 
     SUM(Value) AS TotalValue 
    FROM OriginalRowset 
    GROUP BY [Partition] 
) agg ON orig.[Partition] = agg.[Partition] 

अब देखो कि कैसे आप एक विंडोड कुल साथ भी ऐसा ही कर सकते हैं:

SELECT 
    [Partition], 
    Value, 
    Value * 100.0/SUM(Value) OVER (PARTITION BY [Partition]) AS ValuePercent 
FROM OriginalRowset orig 

बहुत आसान और क्लीनर, है ना?

27

मुझे एक उदाहरण के साथ समझाएं और आप यह देख पाएंगे कि यह कैसे काम करता है।

मान लें कि आप निम्न तालिका DIM_EQUIPMENT है: एसक्यूएल

SELECT VIN, 
    MAKE, 
    MODEL, 
    YEAR, 
    COLOR , 
    COUNT(*) OVER (PARTITION BY YEAR) AS COUNT2 
FROM DIM_EQUIPMENT 

नीचे

VIN   MAKE MODEL YEAR COLOR 
----------------------------------------- 
1234ASDF Ford Taurus 2008 White 
1234JKLM Chevy Truck 2005 Green 
5678ASDF Ford Mustang 2008 Yellow 

भागो परिणाम होगा के रूप में नीचे

VIN   MAKE MODEL YEAR COLOR  COUNT2 
---------------------------------------------- 
1234JKLM Chevy Truck 2005 Green  1 
5678ASDF Ford Mustang 2008 Yellow 2 
1234ASDF Ford Taurus 2008 White  2 

देखें कि क्या हुआ।

आप समूह के बिना वर्ष और पंक्ति के साथ मैच के बिना गिनने में सक्षम हैं।

एक ही परिणाम प्राप्त करने के लिए एक और दिलचस्प तरीका यदि नीचे के रूप में काम के साथ नीचे के रूप में काम करता है, और विशेष रूप से जटिल लोगों को क्वेरी को सरल बना सकता है, जो यहां मामला नहीं है, हालांकि मैं केवल

उपयोग करने की कोशिश कर रहा हूं
WITH EQ AS 
    (SELECT YEAR AS YEAR2, COUNT(*) AS COUNT2 FROM DIM_EQUIPMENT GROUP BY YEAR 
) 
SELECT VIN, 
    MAKE, 
    MODEL, 
    YEAR, 
    COLOR, 
    COUNT2 
FROM DIM_EQUIPMENT, 
    EQ 
WHERE EQ.YEAR2=DIM_EQUIPMENT.YEAR; 
1
  • इसके अलावा Query Petition खण्ड कहा जाता है।
  • Group By खण्ड टुकड़ों में

    • ब्रेक अप डेटा (या विभाजन)
    • अलग विभाजन सीमा से
    • समारोह विभाजन के भीतर निष्पादित करने के लिए इसी तरह के
    • फिर से initialised जब विदाई सीमा
    • को पार

सिंटेक्स:
समारोह (...) से अधिक (col1 col3 द्वारा विभाजन ...)

  • कार्य

    • परिचित कार्यों जैसे COUNT(), SUM(), MIN(), MAX(), आदि
    • नए कार्यों के साथ-साथ (उदाहरण के लिए ROW_NUMBER(), RATION_TO_REOIRT(), आदि।)


उदाहरण के साथ और जानकारी: http://msdn.microsoft.com/en-us/library/ms189461.aspx

-2
prkey whatsthat    cash 
890 "abb    " 32 32 
43  "abbz    " 2 34 
4  "bttu    " 1 35 
45  "gasstuff   " 2 37 
545 "gasz    " 5 42 
80009 "hoo    " 9 51 
2321 "ibm    " 1 52 
998 "krk    " 2 54 
42  "kx-5010   " 2 56 
32  "lto    " 4 60 
543 "mp     " 5 65 
465 "multipower   " 2 67 
455 "O.N.    " 1 68 
7887 "prem    " 7 75 
434 "puma    " 3 78 
23  "retractble   " 3 81 
242 "Trujillo's stuff " 4 85 

क्वेरी का एक परिणाम है कि। स्रोत के रूप में उपयोग की जाने वाली तालिका एक ही है कि इसका कोई अंतिम स्तंभ नहीं है। यह कॉलम तीसरा एक चलती राशि है।

क्वेरी:

SELECT prkey,whatsthat,cash,SUM(cash) over (order by whatsthat) 
    FROM public.iuk order by whatsthat,prkey 
    ; 

(तालिका public.iuk के रूप में चला जाता है)

sql version: 2012 

यह dbase से कुछ ज्यादा है (1986) के स्तर, मैं क्यों 25+ साल की जरूरत किया गया है पता नहीं है इसे खत्म करने के लिए।