SQL OVER () क्लाज - यह कब और क्यों उपयोगी है?


169
    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?


30
कोई फर्क नहीं पड़ता कि आप RDBMS का उपयोग करते हैं, पोस्टग्रेज ट्यूटोरियल मददगार हो सकता है। उदाहरण हैं; मेरी मदद की।
एंड्रयू लाजर

जवाबों:


144

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

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

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

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

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


68

यह 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)

47

यदि आप केवल SalesOrderID द्वारा GROUP करना चाहते थे तो आप 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

42

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

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

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

SQL के नीचे चलाएँ

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

परिणाम नीचे होगा

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

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

आप समूह के बिना YEAR पर गिनने और ROW के साथ मिलान करने में सक्षम हैं।

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

 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;

17

जब पार्टीशन के साथ संयुक्त रूप से OVER क्लॉज बताता है कि क्वेरी की लौटी हुई पंक्तियों का मूल्यांकन करके पूर्ववर्ती फ़ंक्शन कॉल को विश्लेषणात्मक रूप से किया जाना चाहिए। इसे इनलाइन ग्रुप बाय स्टेटमेंट के रूप में सोचें।

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

इसलिए हम EACH UNIQUE SalesOrderID के लिए प्रत्येक ऑर्डर क्यूटी रिकॉर्ड करेंगे, और उस कॉलम का नाम 'कुल' कहलाएगा।

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

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

2
  • जिसे Query Petitionक्लॉज भी कहा जाता है ।
  • Group Byक्लॉज के समान

    • डेटा को विखंडू में विभाजित करें (या विभाजन)
    • विभाजन की सीमाओं से अलग
    • विभाजन के भीतर कार्य करता है
    • बिदाई सीमा पार करते समय पुन: आरंभिक

सिंटैक्स:
फ़ंक्शन (...) OVER (विभाजन द्वारा col1 col3, ...)

  • कार्य

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


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


-3
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+ वर्षों की आवश्यकता क्यों है।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.