अपडेट करें
MySQL 8.0 "विंडो फ़ंक्शंस", SQL सर्वर "विंडो फ़ंक्शंस" के समतुल्य कार्यक्षमता का परिचय देता है (Transact-SQL OVER
द्वारा प्रदान किए गए विभाजन और क्रम के साथ) सिंटैक्स), और Oracle "विश्लेषणात्मक कार्य"।
MySQL संदर्भ मैनुअल 12.21 विंडो फ़ंक्शंस https://dev.mysql .com/doc/refman/8.0/hi/window-functions.html
यहां दिया गया उत्तर 8.0 से पहले के MySQL संस्करणों के लिए एक दृष्टिकोण है।
मूल उत्तर
MySQL अन्य डीबीएमएस (जैसे ओरेकल या एसक्यूएल सर्वर) में उपलब्ध विश्लेषणात्मक कार्यों की तरह चल रहे "संचयी योग" प्राप्त करने के लिए उपयोग किए जाने वाले प्रकार विश्लेषणात्मक फ़ंक्शन प्रदान नहीं करता है।
लेकिन, MySQL का उपयोग करके कुछ विश्लेषणात्मक कार्यों का अनुकरण करना संभव है।
दो व्यावहारिक दृष्टिकोण (कम से कम) हैं:
उप-योग प्राप्त करने के लिए एक सहसंबद्ध उपश्रेणी का उपयोग करना है। यह दृष्टिकोण बड़े सेटों पर महंगा हो सकता है, और जटिल हो सकता है यदि बाहरी क्वेरी पर विधेय जटिल हैं। यह वास्तव में इस बात पर निर्भर करता है कि "एकाधिक तालिकाओं पर एकाधिक जुड़ना" कितना जटिल है। (दुर्भाग्य से, MySQL भी सीटीई का समर्थन नहीं करता है।)
अन्य दृष्टिकोण कुछ नियंत्रण विराम प्रसंस्करण करने के लिए MySQL उपयोगकर्ता चर का उपयोग करना है। यहां "ट्रिक" आपकी क्वेरी से सॉर्ट किए गए परिणामों के लिए है (एक ORDER BY का उपयोग करके) और फिर अपनी क्वेरी को किसी अन्य क्वेरी में लपेटना।
मैं बाद के दृष्टिकोण का एक उदाहरण दूंगा।
MySQL द्वारा संचालन करने के क्रम के कारण, cumulative_total
कॉलम की गणना id
. से मान से पहले की जानी चाहिए और day
वर्तमान पंक्ति से उपयोगकर्ता चर में सहेजे जाते हैं। इस कॉलम को पहले रखना सबसे आसान है।
इनलाइन व्यू को i (नीचे दी गई क्वेरी में) के रूप में उपनामित किया गया है, बस उपयोगकर्ता चर को प्रारंभ करने के लिए है, बस अगर ये पहले से ही सत्र में सेट हैं। यदि उनके पास पहले से ही मान निर्दिष्ट हैं, तो हम उनके वर्तमान मूल्यों को अनदेखा करना चाहते हैं, और ऐसा करने का सबसे आसान तरीका उन्हें प्रारंभ करना है।
आपकी मूल क्वेरी कोष्ठक में लिपटी हुई है, और उसे एक उपनाम दिया गया है, c
नीचे दिए गए उदाहरण में। आपकी मूल क्वेरी में एकमात्र परिवर्तन ORDER BY क्लॉज का जोड़ है, इसलिए हम सुनिश्चित हो सकते हैं कि हम क्वेरी से पंक्तियों को क्रम से संसाधित करते हैं।
बाहरी चयन जाँचता है कि क्या id
और day
वर्तमान पंक्ति से मान पिछली पंक्ति से "मिलान" करें। अगर वे ऐसा करते हैं, तो हम amount
जोड़ते हैं वर्तमान पंक्ति से संचयी उप-योग तक। यदि वे मेल नहीं खाते हैं, तो हम संचयी उप-योग को शून्य पर रीसेट करते हैं, और वर्तमान पंक्ति से राशि जोड़ते हैं (या, अधिक सरलता से, केवल वर्तमान पंक्ति से राशि असाइन करें)।
संचयी कुल की गणना करने के बाद, हम id
. को सहेजते हैं और day
वर्तमान पंक्ति से उपयोगकर्ता चर में मान, इसलिए जब हम अगली पंक्ति को संसाधित करते हैं तो वे उपलब्ध होते हैं।
उदाहरण के लिए:
SELECT IF(@prev_id = c.id AND @prev_day = c.day
,@cumtotal := @cumtotal + c.amount
,@cumtotal := c.amount) AS cumulative_total
, @prev_id := c.id AS `id`
, @prev_day := c.day AS `day`
, c.hr
, c.amount AS `amount'
FROM ( SELECT @prev_id := NULL
, @prev_day := NULL
, @subtotal := 0
) i
JOIN (
select id, day, hr, amount from
( //multiple joins on multiple tables)a
left join
(//unions on multiple tables)b
on a.id=b.id
ORDER BY 1,2,3
) c
यदि अंतिम कॉलम के रूप में संचयी कुल के साथ कॉलम को एक अलग क्रम में वापस करना आवश्यक है, तो एक विकल्प है कि पूरे स्टेटमेंट को माता-पिता के सेट में लपेटना है, और उस क्वेरी को इनलाइन व्यू के रूप में उपयोग करना है:
SELECT d.id
, d.day
, d.hr
, d.amount
, d.cumulative_total
FROM (
// query from above
) d