महत्वपूर्ण: कृपया MySQL 8+ में अपग्रेड करने पर विचार करें और परिभाषित और प्रलेखित ROW_NUMBER () फ़ंक्शन का उपयोग करें, और MySQL के प्राचीन संस्करण तक सीमित फीचर से बंधे पुराने हैक को खोदें
अब यहाँ उन हैक्स में से एक है:
इन-क्वेरी चर का उपयोग करने वाले उत्तर यहां ज्यादातर / सभी इस तथ्य को अनदेखा करते दिखते हैं कि दस्तावेज़ीकरण कहता है (paraphrase):
ऊपर से नीचे तक के क्रम में मूल्यांकन की जा रही चयन सूची में वस्तुओं पर भरोसा न करें। एक सेलेक्ट आइटम में वैरिएबल असाइन न करें और उन्हें दूसरे में उपयोग करें
इस प्रकार, वहाँ एक जोखिम है जो वे गलत उत्तर का मंथन करेंगे, क्योंकि वे आम तौर पर ए
select
(row number variable that uses partition variable),
(assign partition variable)
यदि इनका मूल्यांकन नीचे किया जाता है, तो पंक्ति संख्या काम करना बंद कर देगी (विभाजन नहीं)
इसलिए हमें निष्पादन की गारंटी के साथ कुछ का उपयोग करने की आवश्यकता है। मामला दर्ज करें:
SELECT
t.*,
@r := CASE
WHEN col = @prevcol THEN @r + 1
WHEN (@prevcol := col) = null THEN null
ELSE 1 END AS rn
FROM
t,
(SELECT @r := 0, @prevcol := null) x
ORDER BY col
जैसा कि रूपरेखा ld, prevcol के असाइनमेंट का क्रम महत्वपूर्ण है - मौजूदा रो की मौजूदा पंक्ति के मूल्य से तुलना की जानी चाहिए, इससे पहले कि हम इसे वर्तमान पंक्ति से एक मान असाइन करें (अन्यथा यह मौजूदा पंक्तियों का कॉल मान होगा, न कि पिछली पंक्ति का कॉल मान) ।
यहां बताया गया है कि यह एक साथ कैसे फिट होता है:
पहले WHEN का मूल्यांकन किया जाता है। यदि इस पंक्ति का कर्नल पिछली पंक्ति के कॉल के समान है तो @r वृद्ध हो जाता है और CASE से वापस आ जाता है। यह रिटर्न लीड मान @r में संग्रहीत है। यह MySQL की एक विशेषता है जो असाइनमेंट परिणाम पंक्तियों में @r में दिए गए नए मान को लौटाता है।
परिणाम सेट पर पहली पंक्ति के लिए, @prevcol अशक्त है (यह उपनगरीय क्षेत्र में नल के लिए आरम्भिक है) इसलिए यह विधेय गलत है। यह पहला विधेय भी हर बार कर्नल परिवर्तन (वर्तमान पंक्ति पिछली पंक्ति के लिए अलग है) गलत देता है। इसके कारण दूसरे WHEN का मूल्यांकन किया जाता है।
दूसरा जब विधेय हमेशा गलत होता है, और यह @prevcol को एक नया मान प्रदान करने के लिए विशुद्ध रूप से मौजूद होता है। क्योंकि यह पंक्ति का कर्नल पिछली पंक्ति के कर्नल से भिन्न है (हम इसे जानते हैं क्योंकि यदि यह समान होता, तो पहले WHEN का उपयोग किया गया होता), हमें इसे अगली बार परीक्षण के लिए रखने के लिए नया मान असाइन करना होगा। क्योंकि असाइनमेंट बनाया गया है और फिर असाइनमेंट के परिणाम की तुलना नल के साथ की जाती है, और अशक्त के बराबर कुछ भी गलत है, यह विधेय हमेशा गलत होता है। लेकिन कम से कम इसका मूल्यांकन करने वाले ने इस पंक्ति से कॉल के मूल्य को रखने का अपना काम किया, इसलिए इसका मूल्यांकन अगली पंक्ति के कॉल वैल्यू के खिलाफ किया जा सकता है
क्योंकि दूसरा WHEN झूठा है, इसका मतलब उन परिस्थितियों में है, जहां हम (col) विभाजन कर रहे कॉलम को बदल दिया है, यह ELSE है जो @r के लिए एक नया मान देता है, क्रमांक 1 से पुनः आरंभ
हम इसे ऐसी स्थिति में ले जाते हैं जहाँ:
SELECT
t.*,
ROW_NUMBER() OVER(PARTITION BY pcol1, pcol2, ... pcolX ORDER BY ocol1, ocol2, ... ocolX) rn
FROM
t
सामान्य रूप है:
SELECT
t.*,
@r := CASE
WHEN col1 = @pcol1 AND col2 = @pcol2 AND ... AND colX = @pcolX THEN @r + 1
WHEN (@pcol1 := pcol1) = null OR (@pcol2 := col2) = null OR ... OR (@pcolX := colX) = null THEN null
ELSE 1
END AS rn
FROM
t,
(SELECT @r := 0, @pcol1 := null, @pcol2 := null, ..., @pcolX := null) x
ORDER BY pcol1, pcol2, ..., pcolX, ocol1, ocol2, ..., ocolX
फुटनोट:
पीसीओल में पी का अर्थ है "विभाजन", ओ में चॉकलेट का अर्थ है "आदेश" - सामान्य रूप में मैंने दृश्य अव्यवस्था को कम करने के लिए चर नाम से "प्रचलित" को गिरा दिया
चारों ओर के कोष्ठक (@pcolX := colX) = null
महत्वपूर्ण हैं। उनके बिना आप @pcolX को अशक्त कर देंगे और चीजें काम करना बंद कर देंगी
यह एक समझौता है कि परिणाम सेट को विभाजन कॉलम द्वारा भी आदेश दिया जाना है, पिछले कॉलम के लिए वर्क आउट की तुलना में। आप इस प्रकार एक पंक्ति के अनुसार अपने पंक्तिबद्ध आदेश नहीं दे सकते हैं, लेकिन आपके परिणाम सेट दूसरे के लिए आदेश दिया गया हो सकता है कि आप इसे सबक्वेरी के साथ हल करने में सक्षम हो सकते हैं, लेकिन मेरा मानना है कि डॉक्स यह भी बताता है कि जब तक लिमिट का उपयोग नहीं किया जाता है तब तक उपशमन आदेश को अनदेखा किया जा सकता है और यह प्रभावित हो सकता है प्रदर्शन
मैंने यह परीक्षण करने से परे विलम्ब नहीं किया है कि विधि काम करती है, लेकिन अगर कोई जोखिम है कि दूसरी WHEN में विधेय को कहां से अनुकूलित किया जाएगा (अशक्त की तुलना में कुछ भी अशक्त / गलत है तो असाइनमेंट चलाने में परेशान क्यों हों) और निष्पादित नहीं किया गया , यह भी बंद हो जाता है। यह मेरे अनुभव में नहीं लगता है, लेकिन मैं ख़ुशी से टिप्पणियों को स्वीकार करूंगा और समाधान का प्रस्ताव कर सकता हूं यदि यह यथोचित रूप से हो सकता है
हो सकता है कि आपके स्तंभों के वास्तविक प्रकारों में @pcolX बनाने वाले नलियों को, उप-वर्ग में, जो @pcolX चर बनाता है, अर्थात: select @pcol1 := CAST(null as INT), @pcol2 := CAST(null as DATE)
greatest-n-per-group
इसी तरह के सवालों के लिए आपका मार्गदर्शन करने के लिए टैग किया गया।