2012-10-04 16 views
6

करने के लिए उपयोगकर्ता चर का उपयोग कर अतः उपयोगकर्ता चर का उपयोग का सुझाव पर नंबर पंक्तियों

यहाँ मैं अक्सर उत्तर खोजने के लिए उपयोगकर्ता चर का उपयोग करना कुछ बात या अन्य नंबर पर। शायद सबसे स्पष्ट उदाहरण किसी दिए गए परिणाम सेट से प्रत्येक दूसरी पंक्ति का चयन करने के लिए एक प्रश्न होगा। (यह प्रश्न और प्रश्न this answer के समान है, लेकिन यह this उत्तर था जो वास्तव में इस प्रश्न को ट्रिगर करता था)।गारंटी जब संख्या पंक्तियों

SELECT * 
FROM (SELECT *, (@row := @row + 1) AS rownum 
     FROM (SELECT @row := 0) AS init, tablename 
     ORDER BY tablename.ordercol 
    ) sub 
WHERE rownum % 2 = 1 

यह दृष्टिकोण आम तौर पर काम करता प्रतीत होता है।

कारण, सावधान

दूसरी ओर होने के लिए MySQ docs राज्य:

एक सामान्य नियम के रूप में, आप एक उपयोगकर्ता चर को कोई मान निर्दिष्ट नहीं किया जाना चाहिए और एक ही कथन में मूल्य पढ़ । आपको परिणाम मिलने वाले परिणाम मिल सकते हैं, लेकिन इसकी गारंटी नहीं है। उपयोगकर्ता चर शामिल अभिव्यक्तियों के मूल्यांकन के लिए आदेश अनिर्धारित है और किसी दिए गए कथन में निहित तत्वों के आधार पर बदल सकता है; इसके अलावा, यह आदेश MySQL सर्वर के रिलीज़ के बीच समान होने की गारंटी नहीं है।

कोर सवाल

तो मेरे सवाल का कैसे वर्तमान सर्वर का उपयोग इस तरह के एक आदेश प्राप्त करने के लिए नहीं है और इसके बजाय आप उपयोगकर्ता चर का उपयोग कर सुझाव दिया समाधान गारंटी सब (उचित) परिस्थितियों में और के लिए काम करने के लिए है MySQL के सभी भावी संस्करण।

द्वारा "गारंटी" मेरा मतलब है MySQL दस्तावेज़ या कुछ मानक MySQL दावों के अनुरूप आधिकारिक स्रोत। ऐसे आधिकारिक उत्तरों की कमी, अक्सर उपयोग किए जाने वाले ट्यूटोरियल या MySQL स्रोत कोड के कुछ हिस्सों जैसे अन्य स्रोतों को उद्धृत किया जा सकता है। द्वारा "काम करता है" मेरा मतलब यह है कि परिणाम की प्रति पंक्ति एक बार, और ORDER BY लाइन द्वारा प्रेरित क्रम में असाइनमेंट निष्पादित किया जाएगा।

SELECT * 
FROM (SELECT *, (@row := @row + 1) AS rownum 
     FROM (SELECT @row := 0) AS init, tablename 
     HAVING rownum > 0 
     ORDER BY tablename.ordercol 
    ) sub 
WHERE rownum % 2 = 1 

MySQL 5.5.27 वर्तमान में SQL Fiddle पर स्थापित पर एक खाली परिणाम का उत्पादन करेगा: एक को तोड़ने क्वेरी

की

उदाहरण आपको एक उदाहरण कितनी आसानी से चीजों को विफल देने के लिए। ऐसा लगता है कि HAVING स्थिति rownum अभिव्यक्ति का दो बार मूल्यांकन करने का कारण बनती है, इसलिए अंतिम परिणाम में केवल संख्याएं होंगी। मुझे पता है कि दृश्यों के पीछे क्या चल रहा है, और मैं दावा नहीं कर रहा हूं कि HAVING के साथ क्वेरी बहुत समझ में आता है। मैं सिर्फ यह दिखाना चाहता हूं कि कोड के बीच एक अच्छी रेखा है जो काम करता है और कोड जो बहुत समान दिखता है लेकिन टूटता है।

+0

@ एचवीडी, 'पॉइंटर] (http://bugs.mysql.com/bug.php?id=35893) के लिए धन्यवाद' ROW_NUMBER' सुविधा अनुरोध पर। [डैम्स] (http://stackoverflow.com/users/53341/dems) हाल ही में [मुझे बताया] (http://stackoverflow.com/a/12727443) इस फ़ंक्शन के बारे में। बूट करने के लिए काफी शक्तिशाली, और अच्छी तरह से परिभाषित लगता है। 2008 से उस अनुरोध पर बहुत बुरा प्रतीत होता है। – MvG

+0

मैंने अपनी टिप्पणी हटा दी जब मैंने देखा कि टिप्पणियों में 'ROW_NUMBER' पहले से ही उल्लेख किया गया था और आपके पिछले प्रश्न के उत्तर :) – hvd

+0

[क्या आपने पहले से ही यह लेख पढ़ा है?] (http://www.xaprb.com/blog/2006/12/15/advanced-mysql-user-variable-techniques/) विशेष रूप से भाग 'MySQL क्लाइंट को भेजे जाने तक उपयोगकर्ता चर वाले अभिव्यक्तियों का मूल्यांकन नहीं करता है, ' –

उत्तर

9

आपने कथन को गलत तरीके से पढ़ाया है। यह एकाधिक चर का उपयोग करते समय, SELECT सूची में अभिव्यक्तियों के क्रम से संबंधित है।
जैसा कि प्रस्तुत किया गया है, इस सिंगल-वेरिएबल कथन पर ORDER के पास MySQL के वर्तमान संस्करण तक एक गारंटीकृत आदेश है और उस पाठ में कुछ भी नहीं बताता है कि यह बदल जाएगा।

लेकिन भविष्य की गारंटी? कौन जाने।


तोड़ने क्वेरी के बारे में

, आप फिर से गलत समझा कैसे MySQL काम करता है। आइए अपनी क्वेरी को तोड़ दें। मैनुअल

एक का चयन करें बयान में में इस बयान को ध्यान में रखना, प्रत्येक का चयन अभिव्यक्ति केवल जब ग्राहक को भेजा मूल्यांकन किया जाता है। इसका मतलब यह है कि एक होने, ग्रुप, अथवा खंड क्रम में, एक ऐसा वैरिएबल चयन अभिव्यक्ति की सूची में एक मूल्य असाइन किया गया है काम नहीं करता है के रूप में उम्मीद

की चर्चा करते हुए प्रश्नों के प्रसंस्करण के आदेश मोटे तौर पर है

FROM/JOIN 
WHERE/ON 
GROUP BY/ROLLUP 
HAVING 
UNION 
SELECT 
ORDER BY 
@variable resolution 

आपके "टूटा" क्वेरी एक ही स्तर, जो सिर्फ के बारे में के रूप में/एक कहां का उपयोग कर एक स्तंभ उर्फ ​​के खिलाफ धारा होने के रूप में पाप है के भीतर चर का उपयोग करने के लिए प्रयास करता है। यही कारण है कि आप एक ही क्वेरी-स्तर पर चर का उपयोग करके MySQL चर-आधारित row_numbering समाधान कभी नहीं देखेंगे, यह हमेशा एक सबक्वायरी में होता है। बाहरी क्वेरी को आंतरिक क्वेरी के client माना जा सकता है जिस पर चर/प्लेसहोल्डर-अभिव्यक्ति प्रस्तुत की गई है। आपके तर्क से, आप आसानी से @row सीधे शामिल होने वाले WHERE खंड का उपयोग करके इसे आसानी से तोड़ सकते हैं (हाँ यह रन होगा!)।

+0

मुझे विश्वास नहीं है, लेकिन अगर मैं कथन को मापता हूं, तब भी हमें बिना किसी स्पष्ट गारंटी के छोड़ देता है, और मेरा प्रश्न बनी हुई है। जब आप लिखते हैं कि वर्तमान संस्करण गारंटी आदेश देते हैं, तो क्या आप इसे वापस करने के लिए कोई संदर्भ रखते हैं, या यह सिर्फ व्यक्तिगत अनुभव है? – MvG

+0

व्यक्तिगत अनुभव के अलावा, इस तथ्य पर विचार करें कि समाधान अच्छी तरह से जाना जाता है और उद्धृत किया गया है। मुझे कोई संदर्भ या फीडबैक ढूंढें जो उसने हर समय काम नहीं किया है। यह मेरे लिए काफी अच्छा है। – RichardTheKiwi

+0

[यह उत्तर] (http://stackoverflow.com/a/12171808) टिप्पणियों के अनुसार, [फॉलोअप प्रश्न] (http://stackoverflow.com/q/12243779) के अनुसार, उस प्रश्न के ओपी के लिए काम नहीं किया)। अब तक मैं व्यक्तिगत रूप से इस समस्या को सबसे अधिक संभावित कारण मानता हूं। – MvG

संबंधित मुद्दे