SQL में एक यादृच्छिक पंक्ति का अनुरोध कैसे करें?


510

मैं शुद्ध एसक्यूएल में एक यादृच्छिक पंक्ति (या जितना संभव हो उतना यादृच्छिक के करीब) का अनुरोध कैसे कर सकता हूं?


मैं हमेशा php में क्वेरी के बाद sql से परिणाम प्राप्त करता था ... यह शायद समाधान की सीमा 1 उपांग के अनुसार प्रसंस्करण के लिए बहुत तेज है
CheeseConQueso


2
ऐसा लगता है कि कोई "शुद्ध SQL" समाधान नहीं है जो हर dbms पर चलता है ... उनमें से प्रत्येक के लिए एक समाधान है।
मनु

जवाबों:


734

इस पोस्ट को देखें: SQL एक डेटाबेस तालिका से एक यादृच्छिक पंक्ति का चयन करने के लिए । यह MySQL, PostgreSQL, Microsoft SQL Server, IBM DB2 और Oracle में ऐसा करने के तरीकों के माध्यम से जाता है (निम्नलिखित उस लिंक से कॉपी किया गया है):

MySQL के साथ एक यादृच्छिक पंक्ति चुनें:

SELECT column FROM table
ORDER BY RAND()
LIMIT 1

PostgreSQL के साथ एक यादृच्छिक पंक्ति चुनें:

SELECT column FROM table
ORDER BY RANDOM()
LIMIT 1

Microsoft SQL सर्वर के साथ एक यादृच्छिक पंक्ति चुनें:

SELECT TOP 1 column FROM table
ORDER BY NEWID()

IBM DB2 के साथ एक यादृच्छिक पंक्ति का चयन करें

SELECT column, RAND() as IDX 
FROM table 
ORDER BY IDX FETCH FIRST 1 ROWS ONLY

Oracle के साथ एक यादृच्छिक रिकॉर्ड चुनें:

SELECT column FROM
( SELECT column FROM table
ORDER BY dbms_random.value )
WHERE rownum = 1

30
-1 order by rand()सभी dbs में या समकक्ष पर निर्भर करने के लिए : | यहाँ भी उल्लेख किया गया है
AD7six

20
दस साल पहले किसी लड़के ने कहा कि ORDER BY RAND()गलत इस्तेमाल करना ...
trejder

ORDER BY NEWID () SQL सर्वर पर स्पष्ट रूप से धीमा प्रतीत होता है। मेरी क्वेरी इस तरह दिखती है: शीर्ष 1000 C.CustomerId, ग्राहक C से C.LoginName का चयन करें। C.CustomerId = LA.CustomerId पर आंतरिक रूप से LinkedAccount LA में शामिल हों। C.CustomerId, CL द्वारा CustomerId = CL.CustomerId समूह पर CLLCinerId आंतरिक जोड़ें। LoginName की गिनती (*)> NEWID द्वारा 1 ऑर्डर () NEWID द्वारा "ऑर्डर हटाकर" () लाइन रिटर्न बहुत तेजी से परिणाम देता है।
बेन पावर

3
SQLite के लिए RANDOM () फ़ंक्शन का उपयोग करें।
स्लैम

10
ये समाधान पैमाने नहीं हैं। वे तालिका में रिकॉर्ड की संख्या के O(n)साथ हैं n। कल्पना कीजिए कि आपके पास 1 मिलियन रिकॉर्ड हैं, क्या आप वास्तव में 1 मिलियन यादृच्छिक संख्या या अद्वितीय आईडी उत्पन्न करना चाहते हैं? मैं बल्कि एक यादृच्छिक संख्या के साथ एक COUNT()नई LIMITअभिव्यक्ति में उपयोग और शामिल करना चाहता हूं ।
क्रिश्चियन हुजर

174

जेरेमी जैसे समाधान:

SELECT * FROM table ORDER BY RAND() LIMIT 1

काम करते हैं, लेकिन उन्हें सभी तालिका के अनुक्रमिक स्कैन की आवश्यकता होती है (क्योंकि प्रत्येक पंक्ति से जुड़े यादृच्छिक मूल्य की गणना करने की आवश्यकता होती है - ताकि सबसे छोटा एक निर्धारित किया जा सके), जो मध्यम आकार की तालिकाओं के लिए भी काफी धीमा हो सकता है। मेरी सिफारिश होगी कि किसी तरह के अनुक्रमित संख्यात्मक स्तंभ का उपयोग करें (कई तालिकाओं में उनकी प्राथमिक कुंजी के रूप में ये हैं), और फिर कुछ इस तरह लिखें:

SELECT * FROM table WHERE num_value >= RAND() * 
    ( SELECT MAX (num_value ) FROM table ) 
ORDER BY num_value LIMIT 1

यह लघुगणक समय में काम करता है, भले ही तालिका आकार की हो, यदि num_valueअनुक्रमित हो। एक चेतावनी: यह मानता है कि num_valueसमान रूप से सीमा में वितरित किया गया है 0..MAX(num_value)। यदि आपका डेटासेट दृढ़ता से इस धारणा से विचलित होता है, तो आपको तिरछे परिणाम प्राप्त होंगे (कुछ पंक्तियाँ दूसरों की तुलना में अधिक बार दिखाई देंगी)।


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

1
मुझे पता है कि आमतौर पर रैंड () फ़ंक्शन बहुत उच्च गुणवत्ता के नहीं होते हैं, लेकिन इसके अलावा आप विस्तृत कर सकते हैं कि चयन यादृच्छिक क्यों नहीं होगा?
ग्रे पैंथर

13
SQL सर्वर में पहला गलत है। रैंड () फ़ंक्शन को प्रति पंक्ति केवल एक बार प्रति पंक्ति में नहीं एक बार लागू किया जाता है। तो यह हमेशा पहली पंक्ति का चयन करता है (इसे आज़माएं)।
जेफ वॉकर कोड रेंजर

3
दूसरा यह भी मानता है कि सभी पंक्तियों का हिसाब है: यह संभव है कि वह एक पंक्ति चुन लेगा जिसे हटा दिया गया है।
सैम रूबी

3
@ Sam.Rueby वास्तव में, num_value> = RAND () ... सीमा 1 यह सुनिश्चित करती है कि खाली पंक्तियों को तब तक छोड़ दिया जाएगा जब तक कि यह निर्गमन पंक्ति न मिल जाए।
13

62

मुझे नहीं पता कि यह कितना कुशल है, लेकिन मैंने इसे पहले इस्तेमाल किया है:

SELECT TOP 1 * FROM MyTable ORDER BY newid()

क्योंकि GUID बहुत यादृच्छिक होते हैं, इसलिए ऑर्डर करने का मतलब है कि आपको एक यादृच्छिक पंक्ति मिलती है।


1
मैं एमएस एसक्यूएल सर्वर का उपयोग कर रहा हूं, NEW_ID द्वारा कुछ शीर्ष (1) से कुछ शीर्ष पर जाएं () मेरे लिए बहुत अच्छा काम किया, सलाह के लिए धन्यवाद!

यह ठीक वैसी ही बात हैORDER BY RAND() LIMIT 1
केन ब्लूम

6
यह भी बहुत डेटाबेस विशिष्ट है क्योंकि यह उपयोग करता है TOP 1और newid()
ग्रे

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

1
@Switch और आप किस समाधान का प्रस्ताव करेंगे?
अकमल सालिखोव

31
ORDER BY NEWID()

लेता है 7.4 milliseconds

WHERE num_value >= RAND() * (SELECT MAX(num_value) FROM table)

लेता है 0.0065 milliseconds!

मैं निश्चित रूप से बाद के तरीके के साथ जाऊंगा।


2
दूसरा विकल्प अंतिम पंक्ति नहीं उठाएगा। मुझे पता नहीं क्यों - बस इसे इंगित करते हुए।
वोल्डेमॉर्ट

7
@Voldemort: rand()एक फ्लोटिंग-पॉइंट नंबर देता है nजहाँ 0 < n < 1। मान num_valueलेना एक पूर्णांक है, की वापसी मूल्य rand() * max(num_value)भी एक पूर्णांक के लिए मजबूर किया जाएगा, इस प्रकार दशमलव बिंदु के बाद कुछ भी छोटा कर दिया जाता है। इसलिए, rand() * max(num_value)होगा हमेशा से भी कम हो max(num_value), जिसके कारण अंतिम पंक्ति का चयन किया जा कभी नहीं होगा।
इयान केम्प

यदि मेरा डेटा अक्सर हटा दिया जाता है तो मैं कुशल नहीं रहूंगा - अगर मुझे कोई अंतर मिलता है, तो मुझे पूरी क्वेरी फिर से जमा करनी होगी।
लॉयल कोएनन

1
@ इंकम्प स्टुपिड प्रश्न, तो फिर सिलेक्ट मैक्स (संख्या_) + 1 का उपयोग क्यों नहीं किया जाता है? चूंकि रैंड (या ज्यादातर मामलों में रैंडम) रिटर्न [0,1), आपको मूल्यों की पूरी श्रृंखला मिलेगी। इसके अलावा, हाँ, आप सही हैं, एक क्वेरी ठीक करने के लिए मिला है।
टेकहेड

13

आपने यह नहीं कहा कि आप किस सर्वर का उपयोग कर रहे हैं। SQL सर्वर के पुराने संस्करणों में, आप इसका उपयोग कर सकते हैं:

select top 1 * from mytable order by newid()

SQL Server 2005 और ऊपर में, आप TABLESAMPLEएक यादृच्छिक नमूना प्राप्त करने के लिए उपयोग कर सकते हैं जो कि दोहराने योग्य है:

SELECT FirstName, LastName
FROM Contact 
TABLESAMPLE (1 ROWS) ;

9
MSDN का कहना है कि newid () सही मायने में यादृच्छिक परिणामों के लिए तालमेल से अधिक पसंद किया जाता है: msdn.microsoft.com/en-us/library/ms189108.aspx
एंड्रयू हेजेज 23

7
@ एंड्रयू हेजेज: न्यूड द्वारा आदेश () बहुत महंगा है
आंद्रेई रोनेया

10

SQL सर्वर के लिए

newid () / द्वारा आदेश काम करेगा, लेकिन बड़े परिणाम सेटों के लिए बहुत महंगा होगा क्योंकि इसे हर पंक्ति के लिए एक आईडी उत्पन्न करना होगा, और फिर उन्हें क्रमबद्ध करना होगा।

TABLESAMPLE () एक प्रदर्शन के दृष्टिकोण से अच्छा है, लेकिन आपको परिणामों की गड़गड़ाहट मिलेगी (एक पृष्ठ पर सभी पंक्तियों को वापस कर दिया जाएगा)।

एक बेहतर प्रदर्शन करने वाले सच्चे यादृच्छिक नमूने के लिए, सबसे अच्छा तरीका है कि आप अनियमित रूप से पंक्तियों को फ़िल्टर करें। मुझे निम्न कोड नमूना SQL सर्वर पुस्तकें ऑनलाइन लेख सीमा परिणाम सेट में TABLESAMPLE का उपयोग करके मिला :

यदि आप वास्तव में व्यक्तिगत पंक्तियों का एक यादृच्छिक नमूना चाहते हैं, तो TABLESAMPLE का उपयोग करने के बजाय, पंक्तियों को यादृच्छिक रूप से फ़िल्टर करने के लिए अपनी क्वेरी को संशोधित करें। उदाहरण के लिए, निम्न क्वेरी बिक्री के लगभग एक प्रतिशत पंक्तियों को वापस करने के लिए NEWID फ़ंक्शन का उपयोग करती है। SalesOrderDetail Table:

SELECT * FROM Sales.SalesOrderDetail
WHERE 0.01 >= CAST(CHECKSUM(NEWID(),SalesOrderID) & 0x7fffffff AS float)
              / CAST (0x7fffffff AS int)

SalesOrderID कॉलम CHECKSUM अभिव्यक्ति में शामिल है ताकि NEWID () प्रति पंक्ति के आधार पर नमूना प्राप्त करने के लिए प्रति पंक्ति एक बार मूल्यांकन करे। अभिव्यक्ति CAST (CHECKSUM (NEWID), SalesOrderID) और 0x7fffffff AS फ्लोट / CAST (0x7fffffff AS int) 0 और 1 के बीच एक यादृच्छिक फ्लोट मान का मूल्यांकन करता है।

जब 1,000,000 पंक्तियों वाली तालिका के खिलाफ चलाया जाता है, तो यहां मेरे परिणाम हैं:

SET STATISTICS TIME ON
SET STATISTICS IO ON

/* newid()
   rows returned: 10000
   logical reads: 3359
   CPU time: 3312 ms
   elapsed time = 3359 ms
*/
SELECT TOP 1 PERCENT Number
FROM Numbers
ORDER BY newid()

/* TABLESAMPLE
   rows returned: 9269 (varies)
   logical reads: 32
   CPU time: 0 ms
   elapsed time: 5 ms
*/
SELECT Number
FROM Numbers
TABLESAMPLE (1 PERCENT)

/* Filter
   rows returned: 9994 (varies)
   logical reads: 3359
   CPU time: 641 ms
   elapsed time: 627 ms
*/    
SELECT Number
FROM Numbers
WHERE 0.01 >= CAST(CHECKSUM(NEWID(), Number) & 0x7fffffff AS float) 
              / CAST (0x7fffffff AS int)

SET STATISTICS IO OFF
SET STATISTICS TIME OFF

यदि आप TABLESAMPLE के उपयोग से दूर हो सकते हैं, तो यह आपको सर्वश्रेष्ठ प्रदर्शन देगा। अन्यथा न्यूड () / फिल्टर विधि का उपयोग करें। यदि आपके पास एक बड़ा परिणाम है तो newid () / ऑर्डर अंतिम उपाय होना चाहिए।


4

यदि संभव हो तो, RND () और दोनों पर रिकॉर्ड संख्या फ़ील्ड बनाने की अक्षमता से बचने के लिए संग्रहीत स्टेटमेंट का उपयोग करें।

"रैंडम टेबल से" का चयन करें; 1;
SET @ n = FLOOR (RAND () * (SELECT COUNT (*) FROM table));
EXECUTE रैंडमकार्ड का उपयोग @ एन;

यह समाधान यादृच्छिक पंक्तियों को वापस करने का भी ध्यान रखता है जब अनुक्रमित संख्यात्मक मान का उपयोग किया जाता है जहां ऊपर दिए गए खंड समान रूप से वितरित नहीं होते हैं; भले ही यह id_value> = RAND () * MAX (id_value) का उपयोग करते हुए लगभग समान (निरंतर) समय लेता हो, तो बेहतर है।
गाइड

जहां तक ​​मैं बता सकता हूं कि यह निरंतर समय में नहीं चलता है, यह रैखिक समय में चलता है। सबसे खराब स्थिति में, @n तालिका में पंक्तियों की संख्या के बराबर है, और "तालिका से चयन करें *? 1", "n - 1 पंक्तियों का मूल्यांकन करता है जब तक कि यह अंतिम एक तक न पहुंच जाए।
एंड्रेस रिओप्रियो

3

सबसे अच्छा तरीका है कि एक नया कॉलम में बस उस उद्देश्य के लिए एक यादृच्छिक मूल्य डाल रहा है, और इस तरह से कुछ का उपयोग कर (pseude code + SQL):

randomNo = random()
execSql("SELECT TOP 1 * FROM MyTable WHERE MyTable.Randomness > $randomNo")

यह MediaWiki कोड द्वारा नियोजित समाधान है। बेशक, छोटे मूल्यों के खिलाफ कुछ पूर्वाग्रह हैं, लेकिन उन्होंने पाया कि जब कोई पंक्तियों को नहीं लाया जाता है, तो यह यादृच्छिक मूल्य को शून्य के आसपास लपेटने के लिए पर्याप्त था।

newid () समाधान के लिए एक पूर्ण तालिका स्कैन की आवश्यकता हो सकती है ताकि प्रत्येक पंक्ति को एक नई मार्गदर्शिका सौंपी जा सके, जो बहुत कम प्रदर्शन करने वाली होगी।

रैंड () समाधान बिल्कुल भी काम नहीं कर सकता (यानी MSSQL के साथ) क्योंकि फ़ंक्शन का मूल्यांकन केवल एक बार किया जाएगा, और प्रत्येक पंक्ति को उसी "यादृच्छिक" नंबर को सौंपा जाएगा।


1
जब आप 0 परिणाम प्राप्त करते हैं, तो चारों ओर लपेटना एक काफी यादृच्छिक नमूना प्रदान करता है (न कि केवल "अच्छा पर्याप्त")। यह समाधान बहु-पंक्ति प्रश्नों के लिए लगभग तराजू है ("पार्टी फेरबदल")। समस्या यह है कि परिणाम एक ही समूह में बार-बार चुने जाते हैं। इसके आस-पास जाने के लिए, आपको अपने द्वारा उपयोग किए गए यादृच्छिक संख्याओं को फिर से वितरित करना होगा। आप randomNo का ट्रैक रखकर और परिणाम से अधिकतम (randomness) पर सेट करके धोखा दे सकते हैं, लेकिन फिर p (पंक्ति 1 पर पंक्ति और प्रश्न 2 पर पंक्ति i) == 0, जो उचित नहीं है। मुझे कुछ गणित करने दो, और मैं वास्तव में उचित योजना के साथ तुम्हारे पास वापस आऊंगा।
अल्सेरन


3

रैंड () का उपयोग करने के लिए प्रेरित किया जाता है, क्योंकि यह प्रोत्साहित नहीं किया जाता है , तो आप बस अधिकतम आईडी (= अधिकतम) प्राप्त कर सकते हैं:

SELECT MAX(ID) FROM TABLE;

1.Max (= My_Generated_Random) के बीच एक यादृच्छिक प्राप्त करें

My_Generated_Random = rand_in_your_programming_lang_function(1..Max);

और फिर इस एसक्यूएल को चलाएं:

SELECT ID FROM TABLE WHERE ID >= My_Generated_Random ORDER BY ID LIMIT 1

ध्यान दें कि यह किसी भी पंक्तियों के लिए जांच करेगा कि Ids चुने गए मूल्य की तुलना में एक्वैल या HIGHER हैं। तालिका में नीचे पंक्ति के लिए शिकार करना भी संभव है, और My_Generated_Random की तुलना में एक समान या निम्न आईडी प्राप्त करें, फिर इस तरह क्वेरी को संशोधित करें:

SELECT ID FROM TABLE WHERE ID <= My_Generated_Random ORDER BY ID DESC LIMIT 1

यदि रैंडम आईडी जनरेट नहीं होती है तो क्या होगा? हटाए गए या निष्क्रिय पंक्तियाँ जिन्हें आप उपयोगकर्ता को दिखाना नहीं चाहते हैं, एक परेशानी का कारण होगा।
एलेमे

कुछ भी तो नहीं। आपको CLOSEST मिलता है, सटीक नहीं, आईडी नंबर। यदि आप आईडी = 1 को हटाने के लिए मानते हैं, तो न्यूनतम के साथ 1 का आदान-प्रदान करें।
फोर्सबर्ग

2

जैसा कि @ सन्नू के जवाब पर @ बिलकर्विन की टिप्पणी में बताया गया है ...

जब एक लिमिट के साथ संयोजन किया जाता है, तो मैंने पाया है कि यह वास्तविक पंक्तियों को सीधे क्रम देने के बजाय यादृच्छिक क्रम में शामिल करने के लिए बहुत कम से कम (PostgreSQL 9.1 के साथ) बेहतर प्रदर्शन करता है: जैसे

SELECT * FROM tbl_post AS t
JOIN ...
JOIN ( SELECT id, CAST(-2147483648 * RANDOM() AS integer) AS rand
       FROM tbl_post
       WHERE create_time >= 1349928000
     ) r ON r.id = t.id
WHERE create_time >= 1349928000 AND ...
ORDER BY r.rand
LIMIT 100

बस यह सुनिश्चित करें कि 'r' जटिल क्वेरी में प्रत्येक संभावित कुंजी मान के लिए एक 'रैंड' मान उत्पन्न करता है जो इसके साथ जुड़ा हुआ है लेकिन फिर भी जहां संभव हो 'r' की पंक्तियों की संख्या को सीमित करें।

इंटीग्रेटर के रूप में कास्ट पोस्टग्रेएसक्यूएल 9.2 के लिए विशेष रूप से सहायक है जिसमें पूर्णांक और एकल सटीक फ्लोटिंग प्रकारों के लिए विशिष्ट प्रकार का अनुकूलन है।


1

यहां अधिकांश समाधान छंटनी से बचने का लक्ष्य रखते हैं, लेकिन उन्हें अभी भी एक मेज पर अनुक्रमिक स्कैन करने की आवश्यकता है।

इंडेक्स स्कैन पर स्विच करके अनुक्रमिक स्कैन से बचने का एक तरीका भी है। यदि आप अपनी यादृच्छिक पंक्ति के सूचकांक मूल्य को जानते हैं तो आप लगभग तुरंत परिणाम प्राप्त कर सकते हैं। समस्या यह है - सूचकांक मूल्य का अनुमान कैसे लगाया जाए।

निम्न समाधान PostgreSQL 8.4 पर काम करता है:

explain analyze select * from cms_refs where rec_id in 
  (select (random()*(select last_value from cms_refs_rec_id_seq))::bigint 
   from generate_series(1,10))
  limit 1;

ऊपर दिए गए समाधान से आप अनुमान लगाते हैं कि रेंज 0 से 10 विभिन्न यादृच्छिक सूचकांक मूल्य हैं [आईडी का अंतिम मूल्य]।

संख्या 10 मनमानी है - आप 100 या 1000 का उपयोग कर सकते हैं क्योंकि यह (आश्चर्यजनक रूप से) प्रतिक्रिया समय पर बड़ा प्रभाव नहीं डालता है।

एक समस्या यह भी है - यदि आपके पास विरल आईडी हैं तो आप चूक सकते हैं । समाधान के लिए एक बैकअप योजना है :) इस मामले में यादृच्छिक () क्वेरी द्वारा एक शुद्ध पुराने आदेश। जब संयुक्त आईडी इस तरह दिखता है:

explain analyze select * from cms_refs where rec_id in 
    (select (random()*(select last_value from cms_refs_rec_id_seq))::bigint 
     from generate_series(1,10))
    union all (select * from cms_refs order by random() limit 1)
    limit 1;

संघ नहीं सभी खंड। इस मामले में यदि पहला भाग किसी भी डेटा को लौटाता है तो दूसरा कभी भी निष्पादित नहीं होता है!


1

देर से, लेकिन Google के माध्यम से यहां पहुंच गया, इसलिए पोस्टर के लिए, मैं एक वैकल्पिक समाधान जोड़ूंगा।

एक अन्य दृष्टिकोण है, वैकल्पिक आदेशों के साथ दो बार TOP का उपयोग करना। मुझे नहीं पता कि यह "शुद्ध एसक्यूएल" है, क्योंकि यह TOP में एक वैरिएबल का उपयोग करता है, लेकिन यह SQL Server 2008 में काम करता है। यहां एक उदाहरण है, जिसका उपयोग मैं शब्दकोश शब्दों की तालिका के खिलाफ करता हूं, अगर मुझे एक यादृच्छिक शब्द चाहिए।

SELECT TOP 1
  word
FROM (
  SELECT TOP(@idx)
    word 
  FROM
    dbo.DictionaryAbridged WITH(NOLOCK)
  ORDER BY
    word DESC
) AS D
ORDER BY
  word ASC

बेशक, @idx कुछ बेतरतीब ढंग से उत्पन्न पूर्णांक है जो लक्ष्य तालिका पर 1 से COUNT (*) तक सम्मिलित है। यदि आपका कॉलम अनुक्रमित है, तो आपको इससे भी लाभ होगा। एक और लाभ यह है कि आप इसे एक फ़ंक्शन में उपयोग कर सकते हैं, क्योंकि NEWID () अस्वीकृत है।

अंत में, उपरोक्त क्वेरी NEWID के निष्पादन समय के लगभग 1/10 भाग में चलती है () - उसी तालिका पर क्वेरी का प्रकार। YYMV।


1

आप new id()फ़ंक्शन का उपयोग करके भी देख सकते हैं ।

बस अपनी क्वेरी लिखें और new id()फ़ंक्शन द्वारा ऑर्डर का उपयोग करें । यह काफी यादृच्छिक है।


1

MySQL के लिए यादृच्छिक रिकॉर्ड प्राप्त करने के लिए

 SELECT name
  FROM random AS r1 JOIN
       (SELECT (RAND() *
                     (SELECT MAX(id)
                        FROM random)) AS id)
        AS r2
 WHERE r1.id >= r2.id
 ORDER BY r1.id ASC
 LIMIT 1

अधिक विवरण http://jan.kneschke.de/projects/mysql/order-by-rand/


कई उत्तरों के परीक्षण के बाद मेरा मानना ​​है कि यह सबसे अच्छा है। यह तेजी से लगता है और हर बार एक अच्छा यादृच्छिक संख्या चुनता है। यह @GreyPanther के दूसरे सुझाव के समान है, लेकिन यह उत्तर अधिक यादृच्छिक संख्या चुनता है।
जेफ बेकर

1

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

MS SQL के लिए:

न्यूनतम उदाहरण:

select top 10 percent *
from table_name
order by rand(checksum(*))

सामान्यीकृत निष्पादन समय: 1.00

NewId () उदाहरण:

select top 10 percent *
from table_name
order by newid()

सामान्यीकृत निष्पादन समय: 1.02

NewId()तुच्छ रूप से धीमा है rand(checksum(*)), इसलिए आप इसे बड़े रिकॉर्ड सेट के खिलाफ उपयोग नहीं करना चाहते हैं।

प्रारंभिक बीज के साथ चयन:

declare @seed int
set @seed = Year(getdate()) * month(getdate()) /* any other initial seed here */

select top 10 percent *
from table_name
order by rand(checksum(*) % seed) /* any other math function here */

यदि आपको बीज दिए गए एक ही सेट का चयन करने की आवश्यकता है, तो यह काम करने लगता है।


1

MSSQL में (11.0.5569 पर परीक्षण किया गया) का उपयोग कर

SELECT TOP 100 * FROM employee ORDER BY CRYPT_GEN_RANDOM(10)

की तुलना में काफी तेज है

SELECT TOP 100 * FROM employee ORDER BY NEWID()

1

SQL सर्वर में आप बहुत अच्छा यादृच्छिकता प्राप्त करने के लिए NEWID () के साथ TABLESAMPLE को जोड़ सकते हैं और फिर भी गति हो सकती है। यह विशेष रूप से उपयोगी है यदि आप वास्तव में केवल 1 या पंक्तियों की एक छोटी संख्या चाहते हैं।

SELECT TOP 1 * FROM [table] 
TABLESAMPLE (500 ROWS) 
ORDER BY NEWID()

1

SQL सर्वर 2012+ के साथ आप एकल यादृच्छिक पंक्ति के लिए ऐसा करने के लिए OFFSET FETCH क्वेरी का उपयोग कर सकते हैं

select  * from MyTable ORDER BY id OFFSET n ROW FETCH NEXT 1 ROWS ONLY

जहां आईडी एक पहचान स्तंभ है, और n वह पंक्ति है जिसे आप चाहते हैं - 0 और गणना के बीच एक यादृच्छिक संख्या के रूप में गणना की जाती है () - तालिका का 1 (ऑफसेट 0 सब के बाद पहली पंक्ति है)

यह टेबल डेटा में छेद के साथ काम करता है, जब तक आपके पास ORDER BY क्लॉज के साथ काम करने के लिए एक सूचकांक है। यह यादृच्छिकता के लिए भी बहुत अच्छा है - जैसा कि आप काम करते हैं जो खुद को पास करने के लिए है, लेकिन अन्य तरीकों में निगल्स मौजूद नहीं हैं। इसके अलावा प्रदर्शन बहुत अच्छा है, एक छोटे डेटासेट पर यह अच्छी तरह से पकड़ लेता है, हालांकि मैंने कई मिलियन पंक्तियों के खिलाफ गंभीर प्रदर्शन परीक्षण की कोशिश नहीं की है।



0

मुझे CD-MaN से सहमत होना है: "ORDER BY RAND ()" का उपयोग छोटी तालिकाओं के लिए या जब आप अपना SELECT कुछ ही बार करेंगे तब अच्छी तरह से काम करेंगे।

मैं "num_value> = RAND () * ..." तकनीक का भी उपयोग करता हूं, और अगर मैं वास्तव में यादृच्छिक परिणाम प्राप्त करना चाहता हूं तो मेरे पास तालिका में एक विशेष "यादृच्छिक" कॉलम है जिसे मैं दिन में एक बार अपडेट करता हूं। उस सिंगल UPDATE रन में कुछ समय लगेगा (विशेषकर इसलिए कि आपको उस कॉलम पर एक इंडेक्स रखना होगा), लेकिन हर बार प्रत्येक पंक्ति के लिए यादृच्छिक संख्या बनाने की तुलना में यह तेजी से होता है जब चयन होता है।


0

सावधान रहें क्योंकि TableSample वास्तव में पंक्तियों का एक यादृच्छिक नमूना वापस नहीं करता है। यह आपकी पंक्ति को बनाने वाले 8KB पृष्ठों के यादृच्छिक नमूने को देखने के लिए आपकी क्वेरी को निर्देशित करता है। फिर, आपकी क्वेरी को इन पृष्ठों में निहित डेटा के विरुद्ध निष्पादित किया जाता है। इन पृष्ठों पर डेटा को कैसे वर्गीकृत किया जा सकता है (सम्मिलन आदेश, आदि), यह डेटा को जन्म दे सकता है जो वास्तव में एक यादृच्छिक नमूना नहीं है।

देखें: http://www.mssqltips.com/tip.asp?tip=1308

TableSample के लिए MSDN पृष्ठ में डेटा का एक वास्तविक यादृच्छिक नमूना उत्पन्न करने का तरीका शामिल है।

http://msdn.microsoft.com/en-us/library/ms189108.aspx


0

ऐसा लगता है कि सूचीबद्ध विचारों में से कई अभी भी आदेश का उपयोग करते हैं

हालाँकि, यदि आप एक अस्थायी तालिका का उपयोग करते हैं, तो आप एक यादृच्छिक सूचकांक (जैसे कई समाधान सुझाए गए हैं) असाइन करने में सक्षम हैं, और फिर पहले वाले को पकड़ो जो 0 और 1 के बीच एक मनमाना संख्या से अधिक है।

उदाहरण के लिए (DB2 के लिए):

WITH TEMP AS (
SELECT COMLUMN, RAND() AS IDX FROM TABLE)
SELECT COLUMN FROM TABLE WHERE IDX > .5
FETCH FIRST 1 ROW ONLY

2
इस समाधान पर विचार करने के बाद, मैंने अपने तर्क में एक मूलभूत दोष पाया है। यह तालिका की शुरुआत के निकट समान छोटे सेट मानों को लौटाएगा, क्योंकि मैं मानता हूं कि यदि 0 और 1 के बीच असमान वितरण था, तो 50% संभावना है कि पहली पंक्ति उस मानदंड को पूरा करेगी।
डेविड


0

Dbms_random.value का उपयोग करने के बजाय Oracle के लिए बेहतर समाधान है, जबकि इसे dbms_random.value द्वारा पंक्तियों को ऑर्डर करने के लिए पूर्ण स्कैन की आवश्यकता होती है और यह बड़ी तालिकाओं के लिए काफी धीमा है।

इसके बजाय इसका उपयोग करें:

SELECT *
FROM employee sample(1)
WHERE rownum=1

0

फायरबर्ड के लिए:

Select FIRST 1 column from table ORDER BY RAND()

0

SQL सर्वर 2005 और इसके बाद के संस्करण के लिए, @ GreyPanther के मामलों का जवाब देना जब num_valueनिरंतर मान नहीं है। यह उन मामलों के लिए भी काम करता है जब हमने समान रूप से डेटासेट वितरित नहीं किए हैं और जब num_valueसंख्या नहीं है लेकिन एक अद्वितीय पहचानकर्ता है।

WITH CTE_Table (SelRow, num_value) 
AS 
(
    SELECT ROW_NUMBER() OVER(ORDER BY ID) AS SelRow, num_value FROM table
) 

SELECT * FROM table Where num_value = ( 
    SELECT TOP 1 num_value FROM CTE_Table  WHERE SelRow >= RAND() * (SELECT MAX(SelRow) FROM CTE_Table)
)

-1

एसक्यूएल से रैंडम फ़ंक्शन मदद कर सकता है। इसके अलावा, अगर आप केवल एक पंक्ति तक सीमित करना चाहते हैं, तो बस अंत में इसे जोड़ें।

SELECT column FROM table
ORDER BY RAND()
LIMIT 1
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.