विंडो एक "विंडो" या फ्रेम का उपयोग कैसे करें के साथ कार्य करता है

सभी को नमस्कार। 26 फरवरी को, "MS SQL Server Developer" पाठ्यक्रम पर एक नए समूह में OTUS में कक्षाएं शुरू हुईं इस संबंध में, मैं आपके साथ विंडो फ़ंक्शन के बारे में मेरे प्रकाशन को साझा करना चाहता हूं। वैसे, आने वाले सप्ताह में आप अभी भी समूह में शामिल हो सकते हैं ;-)।





हमारे कार्यों में विंडो फ़ंक्शंस अच्छी तरह से स्थापित हैं, लेकिन कुछ लोग जानते हैं कि RANGE और ROWS फ़्रेम कैसे काम करते हैं।

शायद इसीलिए वे कुछ कम आम हैं। इस लेख का उद्देश्य उपयोग के उदाहरण प्रदान करना है ताकि आपके पास निश्चित रूप से प्रश्न न हों कि "कौन है?" और "इसे कैसे लागू करें?"। सवाल "क्यों?" लेख अयोग्य रहेगा।

आइए देखें कि ओआरईआर () खंड में ORDER बाय का उपयोग करके एक समान प्रभाव कैसे प्राप्त किया जाए।

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

तालिका

Create table sales 
(sales_id INT PRIMARY KEY, sales_dt DATETIME2 DEFAULT GETUTCDATE(),  customer_id INT, item_id INT, cnt INT, price_per_item DECIMAL(19,4));

INSERT INTO sales
(sales_id, sales_dt, customer_id, item_id, cnt, price_per_item)
VALUES
(1, '2020-01-10T10:00:00', 100, 200, 2, 30.15),
(2, '2020-01-11T11:00:00', 100, 311, 1, 5.00),
(3, '2020-01-12T14:00:00', 100, 400, 1, 50.00),
(4, '2020-01-12T20:00:00', 100, 311, 5, 5.00),
(5, '2020-01-13T10:00:00', 150, 311, 1, 5.00),
(6, '2020-01-13T11:00:00', 100, 315, 1, 17.00),
(7, '2020-01-14T10:00:00', 150, 200, 2, 30.15),
(8, '2020-01-14T15:00:00', 100, 380, 1, 8.00),
(9, '2020-01-14T18:00:00', 170, 380, 3, 8.00),
(10, '2020-01-15T09:30:00', 100, 311, 1, 5.00),
(11, '2020-01-15T12:45:00', 150, 311, 5, 5.00),
(12, '2020-01-15T21:30:00', 170, 200, 1, 30.15);

आइए एक सरल क्षण के साथ शुरू करें - SUM फ़ंक्शन में अंतर सॉर्टिंग के साथ और बिना

SELECT sales_id, customer_id, count, 
SUM(count) OVER () as total,
SUM(count) OVER (ORDER BY customer_id) AS cum,
SUM(count) OVER (ORDER BY customer_id, sales_id) AS cum_uniq
FROM sales
ORDER BY customer_id, sales_id;



आइए पहले अगोचर रेक को देखें, आपको कैसे लगता है कि कोड को पढ़ते समय कितने डेवलपर्स सोचते हैं कि सह और कम्युनीक समान हैं? थोड़ा सोचो? शायद, लेकिन क्योंकि यहां यह स्पष्ट है, और क्या यह इतना स्पष्ट है कि आवेदन में कोड पढ़ते समय, और यहां तक ​​कि सॉर्ट फ़ील्ड की इतनी स्पष्ट गैर-विशिष्टता के साथ भी नहीं।

अब हमारी अद्भुत खिड़की खोलें।

खिड़की, या बल्कि फ्रेम ROWS और RANGE के 2 प्रकार हैं, पहले ROWS पता करें।
फ़्रेम प्रतिबंध विकल्प:

  1. वर्तमान पंक्ति / रेंज और वर्तमान पंक्ति के वास्तविक मूल्य से पहले सब कुछ
    असीम के बीच के पिछले
    के पिछले असीम के बीच और वर्तमान पंक्ति
  2. वर्तमान पंक्ति / श्रेणी और उसके बाद सब कुछ
    घटता क्रम और कम हो रही है
  3. पहले और बाद में कितने लाइनों निर्दिष्ट (रेंज के लिए समर्थित नहीं) शामिल करने के लिए
    के बीच एन पूर्ववर्ती और एन के बाद
    के बाद वर्तमान पंक्ति और एन के बीच
    पूर्ववर्ती और वर्तमान पंक्ति एन के बीच

लेकिन कार्रवाई में फ्रेम देखें।

हम SUM फ़ंक्शन के लिए "विंडो" को वर्तमान लाइन और सभी पिछले वाले पर खोलते हैं, जैसा कि आप देख सकते हैं, यह ASC सॉर्टिंग के साथ मेल खाता है

SELECT sales_id, customer_id, cnt, 
SUM(cnt) OVER (ORDER BY customer_id, sales_id) AS cum_uniq,
SUM(cnt) OVER (ORDER BY customer_id, sales_id ROWS UNBOUNDED PRECEDING) AS current_and_all_before,
SUM(cnt) OVER (ORDER BY customer_id, sales_id ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) AS current_and_all_before2
FROM sales
ORDER BY customer_id, sales_id;



उसी समय, मैं आपको याद दिलाना चाहता हूं कि विंडो में ओआरई () क्लॉज में सॉर्ट क्रम खुद ही क्वेरी में सॉर्ट क्रम से संबंधित नहीं है, उदाहरण में यह गणना को आसान बनाने के लिए समान है यदि आप गणना और फ़ंक्शन की समझ के बारे में निर्णय लेते हैं।

SELECT sales_id, customer_id, cnt, 
SUM(cnt) OVER (ORDER BY customer_id, sales_id) AS cum_uniq,
SUM(cnt) OVER (ORDER BY customer_id, sales_id ROWS UNBOUNDED PRECEDING) AS current_and_all_before,
SUM(cnt) OVER (ORDER BY customer_id, sales_id ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) AS current_and_all_before2
FROM sales
ORDER BY cnt;



अब हम फ्रेम की कार्यक्षमता को देखते हैं जब हम बाद की सभी लाइनों को शामिल करते हैं।

SELECT sales_id, customer_id, cnt, 
SUM(cnt) OVER (ORDER BY customer_id, sales_id ROWS BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING) AS current_and_all_frame,
SUM(cnt) OVER (ORDER BY customer_id DESC, sales_id DESC) AS current_and_all_order_desc
FROM sales
ORDER BY customer_id, sales_id;



जैसा कि आप यहां देख सकते हैं, यदि आप रिवर्स सॉर्टिंग का उपयोग करते हैं, तो आप एक समान कार्य के लिए भी एक ही परिणाम प्राप्त कर सकते हैं - लेकिन ROWS थोड़ा अधिक स्थिर है, क्योंकि यदि आपके सॉर्टिंग फ़ील्ड अद्वितीय नहीं हैं, तो आप समान मूल्यों के रूप में एक आश्चर्य प्राप्त कर सकते हैं।

और अंत में, एक विकल्प जो अब प्रकार से नकल नहीं किया जा सकता है, जब हम एक विशिष्ट संख्या में लाइनों को निर्दिष्ट करते हैं जिन्हें फ्रेम में शामिल किया जाना चाहिए

SELECT sales_id, customer_id, cnt, 
SUM(cnt) OVER (ORDER BY customer_id, sales_id ROWS BETWEEN 1 PRECEDING AND CURRENT ROW) AS before_and_current,
cnt,
SUM(cnt) OVER (ORDER BY customer_id, sales_id ROWS BETWEEN CURRENT ROW AND 1 FOLLOWING) AS current_and_1_next,
cnt,
SUM(cnt) OVER (ORDER BY customer_id, sales_id ROWS BETWEEN 2 PRECEDING AND 2 FOLLOWING) AS before2_and_2_next
FROM sales
ORDER BY customer_id, sales_id;



इस विकल्प में, आप पहले से ही इंगित करते हैं कि कौन सी लाइनें सीमा में हैं, और मेरी राय में, यह परिणामों से सबसे स्पष्ट है।

ROWS और RANGE में अंतर


अंतर यह है कि ROWS एक पंक्ति पर और RANGE एक सीमा पर संचालित होता है। सच है, यह नाम से स्पष्ट है, लेकिन व्यवहार में थोड़ा समझाता है?

आइए तस्वीर देखें (लेख के तल पर स्रोत)





अब, अगर हम ध्यान से देखें, तो यह स्पष्ट हो जाएगा कि सॉर्ट पैरामीटर के समान मूल्य वाले पंक्तियों को एक सीमा कहा जाता है।

जैसा कि ऊपर उल्लेख किया गया है, ROWS केवल एक स्ट्रिंग तक सीमित है, जबकि RANGE उन मिलान मूल्यों की पूरी श्रृंखला को कैप्चर करता है जिन्हें आप ORDER BY विंडो फ़ंक्शन में निर्दिष्ट करते हैं।

SELECT sales_id, customer_id, cnt, 
SUM(cnt) OVER (ORDER BY customer_id) AS cum_uniq,
cnt,
SUM(cnt) OVER (ORDER BY customer_id ROWS UNBOUNDED PRECEDING) AS current_and_all_before,
customer_id,
cnt,
SUM(cnt) OVER (ORDER BY customer_id RANGE UNBOUNDED PRECEDING) AS current_and_all_before2
FROM sales
ORDER BY 2, sales_id;



ROWS - हमेशा एक विशिष्ट लाइन पर संचालित होता है, भले ही छंटाई अद्वितीय न हो, लेकिन RANGE केवल अवधि को छँटाई वाले क्षेत्रों के मिलान मूल्यों के साथ जोड़ती है। इस अर्थ में, कार्यक्षमता SUM () फ़ंक्शन के गैर-विशिष्ट फ़ील्ड द्वारा सॉर्ट करने के व्यवहार के समान है। एक और उदाहरण देखते हैं।

SELECT sales_id, customer_id, price_per_item, cnt, 
SUM(cnt) OVER (ORDER BY customer_id, price_per_item) AS cum_uniq,
cnt,
SUM(cnt) OVER (ORDER BY customer_id, price_per_item ROWS UNBOUNDED PRECEDING) AS current_and_all_before,
customer_id,
cnt,
SUM(cnt) OVER (ORDER BY customer_id, price_per_item RANGE UNBOUNDED PRECEDING) AS current_and_all_before2
FROM sales
ORDER BY 2, price_per_item;




पहले से ही 2 फ़ील्ड हैं और रेंज दोनों क्षेत्रों के मिलान मूल्यों के साथ एक श्रेणी द्वारा निर्धारित की जाती है।

और विकल्प तब होता है जब हम गणना को वर्तमान एक से सभी बाद की पंक्तियों में शामिल करते हैं, जो SUM फ़ंक्शन के मामले में उस मान के साथ मेल खाता है जिसे रिवर्स सॉर्टिंग से प्राप्त किया जा सकता है:

SELECT sales_id, customer_id, price_per_item, cnt, 
SUM(cnt) OVER (ORDER BY customer_id DESC, price_per_item DESC) AS cum_uniq,
cnt,
SUM(cnt) OVER (ORDER BY customer_id, price_per_item ROWS BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING) AS current_and_all_before,
customer_id,
cnt,
SUM(cnt) OVER (ORDER BY customer_id, price_per_item RANGE BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING) AS current_and_all_before2
FROM sales
ORDER BY 2, price_per_item, sales_id desc;



जैसा कि आप देख सकते हैं, RANGE ने फिर से मिलान जोड़े की पूरी श्रृंखला को कैप्चर किया।

इस तथ्य के बावजूद कि ROWS और RANGE की कार्यक्षमता हर बार नए से दूर होती है, इस पर सवाल उठते हैं कि इसका उपयोग कैसे किया जाए। मुझे उम्मीद है कि इस लेख ने यह समझा है कि ROWS और RANGE अलग-अलग कैसे हैं, और अब आपको इस बात पर संदेह नहीं होगा कि इस मामले में इस या उस फ्रेम की क्या आवश्यकता है।

चित्रण स्रोत भिन्नता और ROWS
विंडो फ़ंक्शंस के बारे में बदलें SQL सर्वर 2016 के साथ, मार्क तबलादिलो

पाठ्यक्रम के समय में होगा

All Articles