2011-02-12 13 views
33

मुझे पता है कि अगर मैं इस क्वेरी"ऑर्डर द्वारा ऑर्डर()" - यह कैसे काम करता है?

select top 100 * from mytable order by newid() 

चलाने यह मेरी मेज से 100 यादृच्छिक रिकॉर्ड मिल जाएगा।

हालांकि, मैं थोड़ा उलझन में हूं कि यह कैसे काम करता है, क्योंकि मुझे select सूची में newid() नहीं दिखाई देता है। क्या कोई समझा सकता है? क्या newid() के बारे में कुछ खास है?

+0

ध्यान दें कि यह एक धीमी गति से जिस तरह से जब तक डाटाबेस सर्वर पहचानता 100 यादृच्छिक प्रविष्टियां प्राप्त करने के लिए है इसे अनुकूलित करने के लिए एक ज्ञात पैटर्न के रूप में। – CodesInChaos

+0

यह केवल छद्म-यादृच्छिक है। अगर आपको सुरक्षा के लिए सही यादृच्छिकता की आवश्यकता है, तो इस विधि का कभी भी उपयोग न करें। –

+2

आपके 'ORDER BY' खंड में कॉलम को SQL सर्वर में आपके' SELECT' खंड में दिखाई देने की आवश्यकता नहीं है। – Gabe

उत्तर

30
चुने गए हैं 210

मुझे पता है कि न्यूआईडी() करता है, मैं सिर्फ समझने की कोशिश कर रहा हूं कि यह यादृच्छिक चयन में कैसे मदद करेगा। यह है कि (1) का चयन करें बयान mytable से सब कुछ का चयन करेंगे, (2) प्रत्येक पंक्ति का चयन के लिए, NewID() द्वारा उत्पन्न एक uniqueidentifier पर कील, (3) पंक्तियों इस uniqueidentifier और के आधार पर सॉर्ट (4) क्रमबद्ध सूची से शीर्ष 100 चुनें?

हां। यह काफी सटीक है (सिवाय इसके कि सभी पंक्तियों को क्रमबद्ध करने की आवश्यकता नहीं है)। आप वास्तविक निष्पादन योजना को देखकर इसे सत्यापित कर सकते हैं।

SELECT TOP 100 * 
FROM master..spt_values 
ORDER BY NEWID() 

गणना अदिश ऑपरेटर (मेरे उदाहरण क्वेरी में 2506 तालिका में) प्रत्येक पंक्ति के लिए पर NEWID() कॉलम जोड़ने पर तो तालिका में पंक्तियों शीर्ष 100 चयनित के साथ इस कॉलम के आधार पर हल कर रहे हैं।

एसक्यूएल सर्वर वास्तव में पदों 100 नीचे से पूरे सेट सॉर्ट करने के लिए तो यह एक TOP N तरह ऑपरेटर जो स्मृति में पूरे तरह कार्रवाई करने के लिए प्रयास करता है का उपयोग करता है की जरूरत नहीं है (for small values of N)

Plan

+0

समझ गया! और हाँ, आप सही हैं - एक बार मैंने पूरे सेट से शीर्ष 100 पंक्तियों को निर्धारित करने के बाद, बाकी को क्रमबद्ध करने की आवश्यकता नहीं है। –

4

MSDN के रूप में कहते हैं:

NewID() के प्रकार uniqueidentifier एक अनूठा मूल्य बनाता है।

और आपकी तालिका को इस यादृच्छिक मानों द्वारा क्रमबद्ध किया जाएगा।

+1

धन्यवाद - मुझे पता है कि न्यूआईडी() क्या करता है, मैं बस यह समझने की कोशिश कर रहा हूं कि यह यादृच्छिक चयन में कैसे मदद करेगा। क्या यह है कि [1] चयन कथन Mytable से सब कुछ चुनता है, [2] प्रत्येक पंक्ति के लिए चयनित, न्यूआईडी() द्वारा उत्पन्न एक अनूठे पहचानकर्ता पर ध्यान दें, [3] इस अद्वितीय पहचानकर्ता द्वारा पंक्तियों को क्रमबद्ध करें और [4] शीर्ष पर जाएं क्रमबद्ध सूची से 100? –

10

सामान्य तौर पर इसे इस तरह काम करता है:

  • mytable से सभी पंक्तियों "फंस"
  • NEWID() प्रत्येक पंक्ति
  • पंक्तियों से यादृच्छिक संख्या के अनुसार हल कर रहे हैं के लिए मार डाला जाता है NEWID()
  • 100 पहली पंक्ति
6

कुंजी यहां NEWID फ़ंक्शन है, जो प्रत्येक पंक्ति के लिए स्मृति में एक वैश्विक रूप से अद्वितीय पहचानकर्ता (GUID) उत्पन्न करता है। परिभाषा के अनुसार, GUID अद्वितीय और काफी यादृच्छिक है; इसलिए, जब आप ऑर्डर द्वारा ORDER के साथ उस GUID द्वारा सॉर्ट करते हैं, तो आपको तालिका में पंक्तियों का यादृच्छिक क्रम मिलता है। शीर्ष 10 प्रतिशत (या जो भी प्रतिशत आप चाहते हैं) लेना आपको तालिका में पंक्तियों का एक यादृच्छिक नमूना देगा।

NEWID क्वेरी का प्रस्ताव है; यह सरल है और छोटे टेबल के लिए बहुत अच्छी तरह से काम करता है। हालांकि, जब आप बड़ी टेबल के लिए इसका उपयोग करते हैं तो NEWID क्वेरी में बड़ी कमी होती है। खंड द्वारा ऑर्डर तालिका में सभी पंक्तियों को tempdb डेटाबेस में कॉपी करने का कारण बनता है, जहां उन्हें सॉर्ट किया जाता है। इससे दो समस्याएं आती हैं: सॉर्टिंग ऑपरेशन आमतौर पर इसके साथ जुड़ी एक उच्च लागत होती है। छंटनी बहुत सारी डिस्क I/O का उपयोग कर सकती है और लंबे समय तक चल सकती है। सबसे खराब स्थिति परिदृश्य में, tempdb अंतरिक्ष से बाहर चला सकता है। सबसे अच्छे मामले परिदृश्य में, tempdb डिस्क स्थान की एक बड़ी मात्रा ले सकता है जिसे बिना किसी मैन्युअल सिकंक कमांड के पुनः प्राप्त किया जाएगा। आपको जो पंक्तियों की आवश्यकता है वह यादृच्छिक रूप से पंक्तियों का चयन करने का एक तरीका है जो tempdb का उपयोग नहीं करेगा और तालिका जितनी बड़ी हो जाएगी उतनी धीमी नहीं होगी।

SELECT * FROM master..spt_values 
    WHERE (ABS(CAST(
    (BINARY_CHECKSUM(*) * 
    RAND()) as int)) % 100) < 10 

इस क्वेरी के पीछे मूल विचार यह है कि हम तालिका में प्रत्येक पंक्ति के लिए 0 से 99 के बीच एक यादृच्छिक संख्या उत्पन्न करने के लिए चाहते हैं और फिर उन सभी चुनें: यहां बताया गया है कि ऐसा करने के लिए पर एक नया विचार है पंक्तियां जिनकी यादृच्छिक संख्या निर्दिष्ट प्रतिशत के मूल्य से कम है। इस उदाहरण में, हम पंक्तियों में से लगभग 10 प्रतिशत यादृच्छिक रूप से चुने गए हैं; इसलिए, हम पंक्तियों जिसका यादृच्छिक संख्या के सभी है चुनें कम से कम 10

+0

अच्छा विचार है, लेकिन यह केवल तभी काम करेगा यदि आप 'टॉप एन%' करने का प्रयास कर रहे हैं। यदि आप नियमित रूप से 'टॉप 500' करते हैं तो उदाहरण के लिए यह काम नहीं करेगा। जब तक कि आपके पास कोई अलग तरीका न हो (जिसे मैं सुनना पसंद करूंगा)। धन्यवाद। –

1

उपयोग select top 100 randid = newid(), * from mytable order by randid आप तो स्पष्ट किए जाएंगे ..

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