2008-10-19 17 views
37

में एम्यूलेट MySQL LIMIT क्लॉज जब मैंने Zend Framework's database component पर काम किया, तो हमने LIMIT क्लॉज की कार्यक्षमता को MySQL, PostgreSQL, और SQLite द्वारा समर्थित करने की कोशिश की।माइक्रोसॉफ्ट एसक्यूएल सर्वर 2000

$select = $db->select(); 
$select->from('mytable'); 
$select->order('somecolumn'); 
$select->limit(10, 20); 

डेटाबेस LIMIT का समर्थन करता है, तो यह निम्नलिखित की तरह एक SQL क्वेरी का उत्पादन: यही कारण है, एक प्रश्न बनाने इस तरह से किया जा सकता है है डेटाबेस के ब्रांडों के लिए

SELECT * FROM mytable ORDER BY somecolumn LIMIT 10, 20 

यह किया गया था और अधिक जटिल है कि LIMIT का समर्थन न करें (वह खंड मानक SQL भाषा का हिस्सा नहीं है)। यदि आप पंक्ति संख्याएं उत्पन्न कर सकते हैं, तो संपूर्ण क्वेरी को व्युत्पन्न तालिका बनाएं, और बाहरी क्वेरी में BETWEEN का उपयोग करें। यह ओरेकल और आईबीएम डीबी 2 के लिए समाधान था।

SELECT z2.* 
FROM (
    SELECT ROW_NUMBER OVER(ORDER BY id) AS zend_db_rownum, z1.* 
    FROM (...original SQL query...) z1 
) z2 
WHERE z2.zend_db_rownum BETWEEN @offset+1 AND @[email protected]; 

हालांकि, Microsoft SQL सर्वर 2000 ROW_NUMBER() समारोह नहीं है: तो एक क्वेरी इस तरह से लिख सकते हैं माइक्रोसॉफ्ट SQL सर्वर 2005, एक ऐसी ही पंक्ति संख्या समारोह है।

तो मेरा सवाल यह है कि, क्या आप माइक्रोसॉफ्ट एसक्यूएल सर्वर 2000 में LIMIT कार्यक्षमता अनुकरण करने के लिए पूरी तरह से एसक्यूएल का उपयोग कर सकते हैं? कर्सर या टी-एसक्यूएल या संग्रहीत प्रक्रिया का उपयोग किए बिना। इसे LIMIT, दोनों गिनती और ऑफसेट के लिए दोनों तर्कों का समर्थन करना होगा। एक अस्थायी तालिका का उपयोग कर समाधान भी स्वीकार्य नहीं हैं।

संपादित करें:

एमएस एसक्यूएल सर्वर 2000 के लिए सबसे आम समाधान, नीचे दिए गए एक तरह बनना उदाहरण 75 के माध्यम से पंक्तियों 50 पाने के लिए लगता है:

SELECT TOP 25 * 
FROM ( 
    SELECT TOP 75 * 
    FROM table 
    ORDER BY BY field ASC 
) a 
ORDER BY field DESC; 

बहरहाल, यह नहीं करता है ' यदि कुल परिणाम सेट है तो 60 काम करें, 60 पंक्तियां कहें। आंतरिक क्वेरी 60 पंक्तियों को लौटाती है क्योंकि यह शीर्ष 75 में है। फिर बाहरी क्वेरी पंक्ति 35-60 लौटाती है, जो 50-75 के वांछित "पृष्ठ" में फिट नहीं होती है। असल में, यह समाधान तब तक काम करता है जब तक आपको परिणाम सेट के अंतिम "पृष्ठ" की आवश्यकता न हो जो पेज आकार के एकाधिक न हों।

संपादित करें:

एक अन्य समाधान बेहतर काम करता है, लेकिन केवल तभी जब आप परिणाम सेट मान सकते हैं एक स्तंभ है कि अद्वितीय है में शामिल हैं:

SELECT TOP n * 
FROM tablename 
WHERE key NOT IN (
    SELECT TOP x key 
    FROM tablename 
    ORDER BY key 
); 

निष्कर्ष:

कोई सामान्य

- एमएस एसक्यूएल सर्वर 2000 में LIMIT को अनुकरण करने के लिए प्रोजेक्ट समाधान मौजूद है। यदि आप ROW_NUMBER() फ़ंक्शन का उपयोग कर सकते हैं तो एक अच्छा समाधान मौजूद है एमएस एसक्यूएल सर्वर में आयन 2005.

उत्तर

4
SELECT TOP n * 
FROM tablename 
WHERE key NOT IN (
    SELECT TOP x key 
    FROM tablename 
    ORDER BY key 
    DESC 
); 
+0

हाँ, यह करीब है, लेकिन यह केवल काम करता है जब वहाँ अंतरिम क्वेरी परिणाम में एक अद्वितीय कुंजी है। आप ग्रुप बाय क्वेरी में या एक क्वेरी के लिए कैसे करेंगे जो कई तालिकाओं में शामिल हो? –

4

जब आप LIMIT की जरूरत है केवल, एमएस एसक्यूएल, बराबर टॉप कीवर्ड है ताकि स्पष्ट है। जब आपको ऑफ़सेट के साथ LIMIT की आवश्यकता होती है, तो आप पहले से वर्णित कुछ हैक्स को आजमा सकते हैं, लेकिन वे सभी कुछ ओवरहेड जोड़ते हैं, यानी एक तरफ ऑर्डर करने के लिए और फिर दूसरा, या एक्सपेन्सीव इन ऑपरेशन। मुझे लगता है कि उन सभी कैस्केडों की आवश्यकता नहीं है। मेरे oppinion में सबसे साफ समाधान एसक्यूएल पक्ष पर ऑफसेट के बिना शीर्ष का उपयोग किया जाएगा, और उसके बाद उचित क्लाइंट विधि के साथ आवश्यक प्रारंभिक रिकॉर्ड की तलाश करें, जैसे कि php में mssql_data_seek।हालांकि यह एक शुद्ध एसक्यूएल समाधान नहीं है, मुझे लगता है कि यह सबसे अच्छा है क्योंकि यह किसी भी ओवरहेड को नहीं जोड़ता है (जब आप उन्हें पीछे छोड़ते हैं तो छोड़े गए रिकॉर्ड नेटवर्क पर स्थानांतरित नहीं किए जाएंगे, अगर यह आपको चिंता करता है)।

+0

मैं एप्लिकेशन को डिज़ाइन करते समय आपकी सिफारिश से सहमत हूं। मेरे मामले में, मैं डेटाबेस-एक्सेस फ्रेमवर्क तैयार कर रहा था जिसे एक सतत एपीआई माना जाता था लेकिन डेटाबेस के विभिन्न ब्रांडों के लिए आवश्यक विभिन्न एसक्यूएल उत्पन्न करता था। समाधान एसक्यूएल तैयारी में होना था, न कि fetching में। –

+1

अच्छा विचार, बहुत बहुत धन्यवाद। कुल मिलाकर मुझे लगता है कि आपका समाधान अधिक व्यवहार्य है। – 0plus1

+0

यही कारण है कि मैं एमएसएसएलएल को नापसंद करता हूं! –

5

यहां एक और समाधान है जो केवल SQL सर्वर 2005 में काम करता है और नया क्योंकि यह छोड़कर कथन का उपयोग करता है। लेकिन मैं इसे वैसे भी साझा करता हूं। आप रिकॉर्ड 50 प्राप्त करना चाहते हैं - 75 लिखने:

select * from (
    SELECT top 75 COL1, COL2 
    FROM MYTABLE order by COL3 
) as foo 
except 
select * from (
    SELECT top 50 COL1, COL2 
    FROM MYTABLE order by COL3 
) as bar 
+0

धन्यवाद, ऐसा लगता है कि यह माइक्रोसॉफ्ट एसक्यूएल सर्वर 2005 में भी काम करेगा। यह अभी भी हमें माइक्रोसॉफ्ट एसक्यूएल सर्वर 2000 के लिए कोई अच्छा समाधान नहीं छोड़ता है। लेकिन मुझे लगता है कि 200 9 के बाद से, यह वैसे भी 2000 के लिए समर्थन छोड़ना उचित है। –

+0

हां, यह एसक्यूएल सर्वर 2005 में काम करता है। –

+0

यह चालाक है! मैंने ऐसा करने के बारे में सोचा नहीं था। – jocull

0

मैं अपने ORM में इस लागू करने के लिए के रूप में यह वहाँ बहुत सरल है की कोशिश करेंगे। यदि इसे वास्तव में SQL सर्वर में होना आवश्यक है तो मैं निम्नलिखित linq के लिए sql कथन के लिए linq से sql द्वारा उत्पन्न कोड को देखता हूं और वहां से जाता हूं। एमएसएफटी इंजीनियर जिसने कोड लागू किया था वह कई वर्षों तक एसक्यूएल टीम का हिस्सा था और जानता था कि वह क्या कर रहा था।

वर परिणाम = myDataContext.mytable.Skip (pageIndex * pageSize) .Take (pageSize)

+0

http://msdn.microsoft.com/en-us/library/bb386988.aspx कहता है: "SQL Server 2000 और SQL Server 2005 के लिए अनुवाद अलग है। यदि आप किसी भी प्रश्न के साथ Skip (Of TSource) का उपयोग करने की योजना बना रहे हैं जटिलता, एसक्यूएल सर्वर 2005 का उपयोग करें। " –

+0

मेरा मुद्दा यह है कि इस समस्या के लिए बहुत सारे अच्छे समाधान हैं यदि पूर्व शर्त एमएस एसक्यूएल सर्वर 2005 को चलाने के लिए है। लेकिन उनमें से कुछ एमएस एसक्यूएल सर्वर 2000 पर सामान्य मामले में काम करते हैं। माना जाता है कि यह अब 2011 है, और यह तेजी से कठिन है चल रहे एमएस एसक्यूएल सर्वर 2000 को समय पर चलने के लिए उचित ठहराने के लिए। फिर भी कुछ लोग अभी भी करते हैं! :( –

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