SQL में पंक्तियों को बेतरतीब ढंग से कैसे चुनें?


226

मैं MSSQL सर्वर 2005 का उपयोग कर रहा हूं। मेरे db में, मेरे पास एक टेबल "customerNames" है जिसमें दो कॉलम "Id" और "Name" और लगभग हैं। 1,000 परिणाम।

मैं एक कार्यक्षमता बना रहा हूँ जहाँ मुझे हर बार बेतरतीब ढंग से 5 ग्राहकों को चुनना पड़ता है। क्या कोई मुझे बता सकता है कि एक क्वेरी कैसे बनाई जाए जो हर बार जब क्वेरी निष्पादित होती है तो यादृच्छिक 5 पंक्तियाँ (Id, और Name) प्राप्त होंगी?


रैंडम एक डेटाबेस के लिए एक आम आवश्यकता नहीं है, मैं कुछ SQL के लिए एक लिंक खोजने के लिए आश्चर्यचकित था
Paxic

2
निर्भर करता है कि आप कितनी यादृच्छिकता चाहते हैं। देखें: NEW_ID बनाम रैंड () की तुलना के लिए msdn.microsoft.com/en-us/library/aa175776(SQL.80).aspx
शैनन सेवरेंस

जवाबों:


639
SELECT TOP 5 Id, Name FROM customerNames
ORDER BY NEWID()

उस व्यक्ति ने कहा, आपके प्रश्न के अधिक सामान्य उत्तर के लिए हर कोई इस पृष्ठ पर आता है:

SQL में एक यादृच्छिक पंक्ति का चयन करना

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

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

SELECT column FROM table 
ORDER BY RANDOM() LIMIT 1

3
+1 किसी बाहरी साइट (जैसे स्वीकृत उत्तर) से लिंक करने के बजाय SO पर सीधे उत्तर पोस्ट करने के लिए जो भविष्य के उपयोगकर्ताओं द्वारा इस प्रश्न को देखने पर नीचे जा सकते थे।
रे झोउ

17
क्या यह बड़ी तालिकाओं पर बहुत महंगा हो जाता है, जहां प्रत्येक पंक्ति को एक यादृच्छिक संख्या मिलती है, और फिर एक बड़ी अनइंस्टैंडेड यादृच्छिक संख्या सेट को क्रमबद्ध किया जाता है?
एंड्री

यह शायद ज्यादातर लोगों के लिए स्पष्ट है, लेकिन यह मेरे लिए स्पष्ट नहीं था ... निम्नलिखित क्वेरी को प्रत्येक पंक्ति के लिए एक नया यादृच्छिक मान नहीं मिलेगा: update tbl_vouchers set tbl_UsersID = (select top(1) id from tbl_Users order by NEWID()) - संपादित करें: मुझे टिप्पणियों में काम करने के लिए प्रारूपण नहीं मिल सकता है :(
मीर

आप प्रतिभाशाली! मैं आपसे बहुत नफरत करता हूं क्योंकि मैंने इसे तब तक नहीं देखा था जब तक मैं नहीं गया था और उप प्रश्नों और पंक्ति संख्याओं के साथ एक लंबी लंबी क्वेरी लिखी थी।
ग्रीनकोड

5
चेतावनी: बड़े डेटाबेस के लिए इस पद्धति का बुरा प्रदर्शन होगा। क्या आप उस समय की कल्पना कर सकते हैं जब डेटाबेस में एक लाख प्रविष्टि होने पर प्रत्येक पंक्ति के लिए यादृच्छिक मान उत्पन्न होगा? आप के बारे में अधिक जानकारी और एक बेहतर वैकल्पिक जानकारी यहाँ दे सकते हैं
फ्रांसिस नीगुक्कम


11

यदि कोई व्यक्ति PostgreSQL समाधान चाहता है:

select id, name
from customer
order by random()
limit 5;

यह उत्तर PostgreSQL के लिए अच्छा है, इसे सीमा की आवश्यकता नहीं है।
अलियासो

9

शायद यह साइट सहायता की होगी।

उन लोगों के लिए जो क्लिक नहीं करना चाहते हैं:

SELECT TOP 1 column FROM table
ORDER BY NEWID()

2
कम से कम 1 को 5 के साथ प्रतिस्थापित करना चाहिए :)
रोमन एम

7

यहाँ एक अच्छा Microsoft SQL Server 2005 विशिष्ट समाधान है। उस समस्या से निपटते हैं जहां आप एक बड़े परिणाम सेट के साथ काम कर रहे हैं (सवाल मुझे नहीं पता)।

बड़ी तालिका से बेतरतीब ढंग से पंक्तियों का चयन http://msdn.microsoft.com/en-us/library/cc441928.aspx


5

यदि आपके पास लाखों पंक्तियों वाली तालिका है और प्रदर्शन की परवाह है, तो यह एक बेहतर उत्तर हो सकता है:

SELECT * FROM Table1
WHERE (ABS(CAST(
  (BINARY_CHECKSUM
  (keycol1, NEWID())) as int))
  % 100) < 10

https://msdn.microsoft.com/en-us/library/cc441928.aspx


ध्यान दें कि यह तालिका में लगभग 10% पंक्तियों का चयन करेगा। यदि आपको पंक्तियों की सही संख्या, या कम से कम N पंक्तियों का चयन करने की आवश्यकता है, तो यह दृष्टिकोण काम नहीं करेगा।
लार्स

4

यह एक पुराना प्रश्न है, लेकिन बड़ी संख्या में पंक्तियों वाली तालिका के लिए एक नया क्षेत्र (या तो NEWID (या ORDER BY रैंड ()) लागू करने का प्रयास करना बेहद महंगा होगा। यदि आपके पास वृद्धिशील, अद्वितीय आईडी (और कोई छेद नहीं है) तो GUID या हर एक पंक्ति के समान लागू करने के बजाय चयनित ID के X # की गणना करना अधिक कुशल होगा और फिर शीर्ष X # को लेना होगा।

DECLARE @minValue int;
DECLARE @maxValue int;
SELECT @minValue = min(id), @maxValue = max(id) from [TABLE];

DECLARE @randomId1 int, @randomId2 int, @randomId3 int, @randomId4 int, @randomId5 int
SET @randomId1 = ((@maxValue + 1) - @minValue) * Rand() + @minValue
SET @randomId2 = ((@maxValue + 1) - @minValue) * Rand() + @minValue
SET @randomId3 = ((@maxValue + 1) - @minValue) * Rand() + @minValue
SET @randomId4 = ((@maxValue + 1) - @minValue) * Rand() + @minValue
SET @randomId5 = ((@maxValue + 1) - @minValue) * Rand() + @minValue

--select @maxValue as MaxValue, @minValue as MinValue
--  , @randomId1 as SelectedId1
--  , @randomId2 as SelectedId2
--  , @randomId3 as SelectedId3
--  , @randomId4 as SelectedId4
--  , @randomId5 as SelectedId5

select * from [TABLE] el
where el.id in (@randomId1, @randomId2, @randomId3, @randomId4, @randomId5)

यदि आप कई और पंक्तियों का चयन करना चाहते हैं, तो मैं एक आईडी के साथ एक #tempTable और रैंड () मानों के एक झुंड को पॉप करने के लिए देखूंगा, फिर प्रत्येक रैंड () मान का उपयोग करके अधिकतम-अधिकतम मानों तक ले जाऊंगा। इस तरह आपको सभी @ randomId1 ... n पैरामीटर को परिभाषित करने की आवश्यकता नहीं है। मैंने प्रारंभिक तालिका को पॉप्युलेट करने के लिए CTE का उपयोग करके नीचे एक उदाहरण शामिल किया है।

DECLARE @NumItems int = 100;

DECLARE @minValue int;
DECLARE @maxValue int;
SELECT @minValue = min(id), @maxValue = max(id) from [TABLE];
DECLARE @range int = @maxValue+1 - @minValue;

with cte (n) as (
   select 1 union all
   select n+1 from cte
   where n < @NumItems
)
select cast( @range * rand(cast(newid() as varbinary(100))) + @minValue as int) tp
into #Nt
from cte;

select * from #Nt ntt
inner join [TABLE] i on i.id = ntt.tp;

drop table #Nt;

@Protiguous, आपके द्वारा प्रस्तावित संपादन ने यादृच्छिक चयन को तोड़ दिया। मिनट () और अधिकतम () का उपयोग dbo.Tally64k टेबल पर करने से उपयोगकर्ता pk id> 65556 के साथ एक पंक्ति का चयन करने की अनुमति नहीं देगा।
RIanGillis

तालिका नाम परिवर्तन परीक्षण से बस एक विरूपण साक्ष्य था। वास्तविक तालिका नाम कोई मायने नहीं रखता है, जब तक कि सही तालिका का उपयोग नहीं किया जाता है। न्यूनतम () और अधिकतम () दोनों को एक क्वेरी में दो के बजाय क्वियर किया जा सकता है, जिसे मैं दिखाने की कोशिश कर रहा था।
रक्षात्मक

@Protiguous आह, मुझे लगता है कि अब, मैं उलझन में था क्योंकि आप मिनट-अधिकतम करते समय 0-65k का उपयोग करते थे लेकिन बाद में नहीं। आपके सबसे हालिया संपादन के बाद मैं वास्तव में आपके द्वारा किए गए परिवर्तनों के प्रदर्शन निहितार्थों के बारे में पूछना चाहता था, क्योंकि प्रदर्शन ट्यूनिंग मेरे हितों में से एक है और प्रतीत होता है कि बिना किसी निर्णय के किस तरह का सार्थक निर्णय आपको लगता है कि वास्तव में एक महत्वपूर्ण प्रभाव पड़ सकता है - - क्या 5 SET @ randomId ## कॉल्स पर भी यही बात लागू होगी? या यह अलग है क्योंकि यह वास्तविक तालिका से चयन नहीं है?
RIanGillis

मुझे यकीन नहीं है कि मैं आपके सवाल को समझ सकता हूँ। क्या आप पूछ रहे हैं कि सिर्फ 1 SELECT @ id1 = rand (), @ id2 = rand () .. के बजाय 5 सेट क्यों हैं? ऐसा इसलिए है क्योंकि 1 स्टेटमेंट में एक रैंड () के लिए कई कॉल एक ही परिणाम उत्पन्न करेंगे, इसलिए अलग SET। (रैंड) SQL सर्वर पर एक नियतात्मक कार्य है, मुझे विश्वास है।) मुझे लगता है कि 1 चयन बनाम 5 सेट नैनोसेकंड रेंज प्रदर्शन-वार में है।
प्रोटीज

4
SELECT * FROM TABLENAME ORDER BY random() LIMIT 5; 

पुराना सवाल है, लेकिन यह जवाब मेरे लिए ओरेकल में नहीं चला।
भालू

सेलेक्ट करें * FROM (SELECT * FROM table ORDER BY DBMS_RANDOM.VALUE) जहाँ पर पंक्तिबद्ध संख्या <; @ इसको आज़माएं
नरेंद्र

3

मैंने इसे बड़े डेटा के लिए सबसे अच्छा काम करने के लिए पाया है।

SELECT TOP 1 Column_Name FROM dbo.Table TABLESAMPLE(1 PERCENT);

TABLESAMPLE(n ROWS) or TABLESAMPLE(n PERCENT)यादृच्छिक है, लेकिन TOP nसही नमूना आकार प्राप्त करने के लिए इसे जोड़ने की आवश्यकता है ।

NEWID()बड़े तालिकाओं पर उपयोग करना बहुत धीमा है।


0

जैसा कि मैंने इस लेख में बताया है , SQL परिणाम सेट में फेरबदल करने के लिए, आपको डेटाबेस-विशिष्ट फ़ंक्शन कॉल का उपयोग करने की आवश्यकता होती है।

ध्यान दें कि एक रैंडम फ़ंक्शन का उपयोग करके सेट किए गए एक बड़े परिणाम को बहुत धीमा हो सकता है, इसलिए सुनिश्चित करें कि आप छोटे परिणाम सेट पर ऐसा करते हैं।

यदि आपको एक बड़े परिणाम सेट को फेरबदल करना है और इसे बाद में सीमित करना है, तो ORDER BY खंड में एक यादृच्छिक फ़ंक्शन के बजाय OracleSAMPLE(N) या SQL सर्वर या PostgreSQLTABLESAMPLE में कुछ का उपयोग करना बेहतर है ।

इसलिए, यह मानते हुए कि हमारे पास निम्नलिखित डेटाबेस तालिका है:

यहां छवि विवरण दर्ज करें

और songतालिका में निम्नलिखित पंक्तियाँ :

| id | artist                          | title                              |
|----|---------------------------------|------------------------------------|
| 1  | Miyagi & Эндшпиль ft. Рем Дигга | I Got Love                         |
| 2  | HAIM                            | Don't Save Me (Cyril Hahn Remix)   |
| 3  | 2Pac ft. DMX                    | Rise Of A Champion (GalilHD Remix) |
| 4  | Ed Sheeran & Passenger          | No Diggity (Kygo Remix)            |
| 5  | JP Cooper ft. Mali-Koa          | All This Love                      |

आकाशवाणी

ओरेकल पर, आपको DBMS_RANDOM.VALUEफ़ंक्शन का उपयोग करने की आवश्यकता है , जैसा कि निम्नलिखित उदाहरण द्वारा चित्रित किया गया है:

SELECT
    artist||' - '||title AS song
FROM song
ORDER BY DBMS_RANDOM.VALUE

Oracle पर पूर्वोक्त SQL क्वेरी चलाते समय, हम निम्नलिखित परिणाम प्राप्त करने जा रहे हैं:

| song                                              |
|---------------------------------------------------|
| JP Cooper ft. Mali-Koa - All This Love            |
| 2Pac ft. DMX - Rise Of A Champion (GalilHD Remix) |
| HAIM - Don't Save Me (Cyril Hahn Remix)           |
| Ed Sheeran & Passenger - No Diggity (Kygo Remix)  |
| Miyagi & Эндшпиль ft. Рем Дигга - I Got Love      |

ध्यान दें कि गीतों को यादृच्छिक क्रम में सूचीबद्ध किया जा रहा DBMS_RANDOM.VALUEहै, ORDER BY खंड द्वारा उपयोग किए जाने वाले फ़ंक्शन कॉल के लिए धन्यवाद ।

एस क्यू एल सर्वर

SQL सर्वर पर, आपको NEWIDफ़ंक्शन का उपयोग करने की आवश्यकता है , जैसा कि निम्नलिखित उदाहरण द्वारा चित्रित किया गया है:

SELECT
    CONCAT(CONCAT(artist, ' - '), title) AS song
FROM song
ORDER BY NEWID()

SQL सर्वर पर पूर्वोक्त SQL क्वेरी चलाते समय, हम निम्नलिखित परिणाम सेट प्राप्त करने जा रहे हैं:

| song                                              |
|---------------------------------------------------|
| Miyagi & Эндшпиль ft. Рем Дигга - I Got Love      |
| JP Cooper ft. Mali-Koa - All This Love            |
| HAIM - Don't Save Me (Cyril Hahn Remix)           |
| Ed Sheeran & Passenger - No Diggity (Kygo Remix)  |
| 2Pac ft. DMX - Rise Of A Champion (GalilHD Remix) |

ध्यान दें कि गीतों को यादृच्छिक क्रम में सूचीबद्ध किया जा रहा NEWIDहै, ORDER BY खंड द्वारा उपयोग किए जाने वाले फ़ंक्शन कॉल के लिए धन्यवाद ।

PostgreSQL

PostgreSQL पर, आपको randomफ़ंक्शन का उपयोग करने की आवश्यकता है , जैसा कि निम्नलिखित उदाहरण द्वारा चित्रित किया गया है:

SELECT
    artist||' - '||title AS song
FROM song
ORDER BY random()

PostgreSQL पर पूर्वोक्त SQL क्वेरी चलाते समय, हम निम्नलिखित परिणाम सेट प्राप्त करने जा रहे हैं:

| song                                              |
|---------------------------------------------------|
| 2Pac ft. DMX - Rise Of A Champion (GalilHD Remix) |
| JP Cooper ft. Mali-Koa - All This Love            |
| Ed Sheeran & Passenger - No Diggity (Kygo Remix)  |
| HAIM - Don't Save Me (Cyril Hahn Remix)           |
| Miyagi & Эндшпиль ft. Рем Дигга - I Got Love      |

ध्यान दें कि गीतों को यादृच्छिक क्रम में सूचीबद्ध किया जा रहा randomहै, ORDER BY खंड द्वारा उपयोग किए जाने वाले फ़ंक्शन कॉल के लिए धन्यवाद ।

माई एसक्यूएल

MySQL पर, आपको RANDफ़ंक्शन का उपयोग करने की आवश्यकता है , जैसा कि निम्नलिखित उदाहरण द्वारा चित्रित किया गया है:

SELECT
  CONCAT(CONCAT(artist, ' - '), title) AS song
FROM song
ORDER BY RAND()

MySQL पर उपरोक्त उल्लिखित SQL क्वेरी चलाते समय, हम निम्नलिखित परिणाम सेट प्राप्त करने जा रहे हैं:

| song                                              |
|---------------------------------------------------|
| HAIM - Don't Save Me (Cyril Hahn Remix)           |
| Ed Sheeran & Passenger - No Diggity (Kygo Remix)  |
| Miyagi & Эндшпиль ft. Рем Дигга - I Got Love      |
| 2Pac ft. DMX - Rise Of A Champion (GalilHD Remix) |
| JP Cooper ft. Mali-Koa - All This Love            |

ध्यान दें कि गीतों को यादृच्छिक क्रम में सूचीबद्ध किया जा रहा RANDहै, ORDER BY खंड द्वारा उपयोग किए जाने वाले फ़ंक्शन कॉल के लिए धन्यवाद ।


0

यदि आप बड़ी तालिका का उपयोग कर रहे हैं और 10 प्रतिशत डेटा का उपयोग करना चाहते हैं तो निम्न कमांड को चलाएं: SELECT TOP 10 PERCENT * FROM Table1 ORDER BY NEWID();

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.