কীভাবে এসকিউএল এলোমেলো সারির অনুরোধ করবেন?


510

খাঁটি এসকিউএল-এ আমি কীভাবে একটি এলোমেলো সারি (বা যতটা সম্ভব সত্যিকারের এলোমেলোভাবে কাছে) অনুরোধ করতে পারি?


আমি বরাবরই
এসকিএল


2
দেখে মনে হচ্ছে যে কোনও "খাঁটি এসকিউএল" সমাধান নেই যা প্রতি ডিবিএমএসে চলে ... তাদের প্রত্যেকটির জন্য একটি সমাধান রয়েছে।
মনু

উত্তর:


734

এই পোস্টটি দেখুন: এসকিউএল একটি ডাটাবেস টেবিল থেকে একটি এলোমেলো সারি নির্বাচন করতে । এটি মাইএসকিউএল, পোস্টগ্রেএসকিউএল, মাইক্রোসফ্ট এসকিউএল সার্ভার, আইবিএম ডিবি 2 এবং ওরাকল (নিম্নলিখিত লিঙ্কটি থেকে অনুলিপি করা হয়েছে) এ করার পদ্ধতিগুলির মধ্য দিয়ে যায়:

মাইএসকিউএল সহ একটি এলোমেলো সারিটি নির্বাচন করুন:

SELECT column FROM table
ORDER BY RAND()
LIMIT 1

PostgreSQL সহ একটি এলোমেলো সারিটি নির্বাচন করুন:

SELECT column FROM table
ORDER BY RANDOM()
LIMIT 1

মাইক্রোসফ্ট এসকিউএল সার্ভারের সাথে একটি এলোমেলো সারিটি নির্বাচন করুন:

SELECT TOP 1 column FROM table
ORDER BY NEWID()

আইবিএম ডিবি 2 সহ একটি এলোমেলো সারি নির্বাচন করুন

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

ওরাকল সহ একটি এলোমেলো রেকর্ড নির্বাচন করুন:

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

30
-1 উপর নির্ভর করে order by rand()বা সব dbs এর সমতুল্য: | এখানেও উল্লেখ করা হয়েছে
এডি

20
দশ বছর আগে কোনও লোক বলেছিল যে ব্যবহার ORDER BY RAND()করা ভুল ...
ট্রেজার্ড

নতুন দ্বারা অর্ডার () এসকিউএল সার্ভারে উল্লেখযোগ্যভাবে ধীর হয়ে গেছে বলে মনে হচ্ছে। আমার ক্যোয়ারীটি দেখে মনে হচ্ছে: গ্রাহক সি অভ্যন্তরীণ থেকে শীর্ষস্থানীয় 1000 সি। কাস্টমোরআইডি, সিএল। লোগিননাম সি.কাস্টোমারআইড = এলএ-এর কাস্টোমারআইডের অভ্যন্তরীণ গ্রাহকলোগিন সিএল-তে অন্তর্ভুক্ত করুন। লগইননেম গণনা করা (*)> 1 টি নতুন অর্ডার দিয়ে অর্ডার করুন () "অর্ডার দ্বারা NEWID ()" লাইন মুছে ফেলার ফলে ফলাফল আরও দ্রুত ফিরে আসে।
বেন পাওয়ার

3
এসকিউএলাইট ব্যবহারের জন্য র‌্যান্ডম () ফাংশন ব্যবহার করুন।
স্ল্যাম

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)। যদি আপনার ডেটাসেট দৃ strongly়ভাবে এই অনুমান থেকে বিচ্যুত হয়, আপনি ফলস ফলাফল পাবেন (কিছু সারি অন্যদের তুলনায় আরও প্রায়ই প্রদর্শিত হবে)।


8
দ্বিতীয় পরামর্শটি এলোমেলো নয়। আপনি যে সারিটি বেছে নিতে চলেছেন তা আপনি ভবিষ্যদ্বাণী করতে পারবেন না, তবে আপনাকে যদি বাজি ধরতে হয় তবে আপনি দ্বিতীয় সারিতে বাজি ধরবেন। এবং আপনি কখনই শেষ সারিতে বাজি ধরবেন না, আপনার নাম_মূল্যের বিতরণ যাই হোক না কেন এবং আপনার টেবিলটি কত বড় তা আপনার পক্ষে কম নেওয়া সম্ভব হয় না।
এটিয়েন র্যাকাইন

1
আমি জানি যে সাধারণত র‌্যান্ড () ফাংশনগুলি খুব উচ্চ মানের হয় না, তবে এর বাইরে আপনি কী দয়া করে নির্বাচনটি এলোমেলোভাবে হবে না তা বিস্তারিতভাবে বর্ণনা করতে পারেন?
গ্রে প্যান্থার

13
প্রথমটি হ'ল এসকিউএল সার্ভারে র্রং। RAND () ফাংশনটি প্রতি ক্যোয়ারী প্রতি একবারে একবারে নয় একবার ব্যবহৃত হয়। সুতরাং এটি সর্বদা প্রথম সারিটি নির্বাচন করে (চেষ্টা করে দেখুন)।
জেফ ওয়াকার কোড রেঞ্জার

3
দ্বিতীয়টি এটিও ধরে নিয়েছে যে সমস্ত সারিটির জন্য জবাব দেওয়া হয়েছে: এটি সম্ভবত মুছে ফেলা একটি সারি বেছে নেবে।
স্যাম রুয়েবি

3
@ স্যাম.আরউবি প্রকৃতপক্ষে, num_value> = RAND () ... সীমা 1 নিশ্চিত করে যে খালি সারিগুলি অস্তিত্বযুক্ত সারিটি না পাওয়া পর্যন্ত এড়িয়ে যাবে।
ঘোর্ড

62

আমি জানি না এটি কতটা দক্ষ, তবে আমি এটি আগে ব্যবহার করেছি:

SELECT TOP 1 * FROM MyTable ORDER BY newid()

কারণ জিইউইডিগুলি বেশ এলোমেলো, অর্ডার করার অর্থ আপনি একটি এলোমেলো সারি পান।


1
আমি এমএস এসকিউএল সার্ভার ব্যবহার করছি, শীর্ষস্থানীয় 1 * কিছু_সামান্য_নামীর অর্ডার থেকে নতুন () আমার পক্ষে দুর্দান্ত কাজ করেছে, পরামর্শের জন্য ধন্যবাদ!

ঠিক একই জিনিসটি ORDER BY RAND() LIMIT 1
কেন ব্লুম

6
এটি খুব ডাটাবেস নির্দিষ্ট কারণ এটি ব্যবহার করে TOP 1এবং newid()
ধূসর

12
এটি একটি খারাপ ধারণা। প্রতিটি কলামকে ভারতবর্ষে সূচিযুক্ত না করা হলে এই পদ্ধতিটি সূচি ব্যবহার করবে না। 100 মিলিয়ন রেকর্ড সহ সারণী একটি রেকর্ড পেতে খুব দীর্ঘ সময় নিতে পারে।
স্যুইচ করুন

1
@ সুইচ এবং আপনি কি সমাধান প্রস্তাব করবেন?
আকমল সালিকভভ

31
ORDER BY NEWID()

লাগে 7.4 milliseconds

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

লাগে 0.0065 milliseconds!

আমি অবশ্যই উত্তরোত্তর পদ্ধতিতে যাব।


2
দ্বিতীয় বিকল্পটি শেষ সারিটি বেছে নেবে না। আমি জানি না কেন - কেবল এটি নির্দেশ করে।
ভলডেমর্ট

7
@ ভলডেমর্ট: যেখানে rand()একটি ভাসমান-পয়েন্ট নম্বর দেয় । ধরে নেওয়া একটি একটি পূর্ণসংখ্যা, এর ফেরতের মানটিও একটি পূর্ণসংখ্যার সাথে জোর করা হবে, সুতরাং দশমিক বিন্দুর পরে কোনও কিছু কেটে ফেলা হবে। তাই, হবে সবসময় কম হওয়া , যা কেন শেষ সারি নির্বাচিত করা হবে না। n0 < n < 1num_valuerand() * max(num_value)rand() * max(num_value)max(num_value)
ইয়ান কেম্প

আমার ডেটা প্রায়শই মুছে ফেলা হলে আমি দক্ষ হব না - যদি আমি কোনও ফাঁক খুঁজে পাই তবে আমাকে পুরো ক্যোয়ারীটি আবার চালাতে হবে।
লুইক কোনেন

1
@ ইয়ানকেম্প মূ question় প্রশ্ন, তাহলে কেন কেবল সलेक्ट ম্যাক্স (নাম_মূল্য) + 1 ব্যবহার করবেন না? যেহেতু র্যান্ড (বা বেশিরভাগ ক্ষেত্রে র্যান্ডোম) [0,1) প্রদান করে, আপনি মানগুলির পুরো পরিসীমা পাবেন। এছাড়াও, হ্যাঁ, আপনি ঠিক বলেছেন, একটি প্রশ্নের সমাধান করতে হবে।
টেকহেইড

13

আপনি কোন সার্ভার ব্যবহার করছেন তা আপনি বলেননি। এসকিউএল সার্ভারের পুরানো সংস্করণগুলিতে আপনি এটি ব্যবহার করতে পারেন:

select top 1 * from mytable order by newid()

এসকিউএল সার্ভার 2005 এবং তারপরে, আপনি TABLESAMPLEপুনরাবৃত্তিযোগ্য একটি এলোমেলো নমুনা পেতে ব্যবহার করতে পারেন :

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

9
দুটিই MSDN বলেছেন newid () সত্যিই র্যান্ডম ফলাফলের জন্য tablesample বেশী প্রাধান্য হয়: msdn.microsoft.com/en-us/library/ms189108.aspx
অ্যান্ড্রু হেজেস

7
@ অ্যান্ড্রু হেজেস: নতুনের অর্ডার () খুব ব্যয়বহুল
আন্দ্রে রিনিয়া

10

এসকিউএল সার্ভারের জন্য

newid () / অর্ডার বাই কাজ করবে তবে বড় রেজাল্ট সেটের জন্য খুব ব্যয়বহুল হবে কারণ এটি প্রতিটি সারির জন্য একটি আইডি উত্পন্ন করতে হবে এবং তারপরে সেগুলি বাছাই করতে হবে।

টেবিলস্যাম্পল () পারফরম্যান্সের দিক থেকে ভাল তবে আপনি ফলাফলের ক্লাম্পিং পাবেন (কোনও পৃষ্ঠায় সমস্ত সারি ফিরে আসবে)।

সত্যিকারের এলোমেলো নমুনার আরও ভাল পারফরম্যান্সের জন্য, এলোমেলোভাবে সারিগুলি ফিল্টার করা সবচেয়ে ভাল উপায়। আমি এসকিউএল সার্ভার বই অনলাইন নিবন্ধে সারণি নমুনা ব্যবহার করে ফলাফল সেটগুলি সীমাবদ্ধ করে নিম্নলিখিত কোডের নমুনা পেয়েছি :

আপনি যদি সত্যিই পৃথক সারিগুলির একটি এলোমেলো নমুনা চান তবে সারণীটি স্যাম্বল ব্যবহার না করে এলোমেলোভাবে সারিগুলি ফিল্টার করার জন্য আপনার ক্যোয়ারীটি পরিবর্তন করুন। উদাহরণস্বরূপ, নিম্নলিখিত কোয়েরি বিক্রয়ের সারিগুলির প্রায় এক শতাংশ ফেরত দিতে NEWID ফাংশনটি ব্যবহার করে a সেলস অর্ডারডেটেল টেবিল:

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

সেলসঅর্ডারআইডি কলামটি চেকসুম এক্সপ্রেশনটিতে অন্তর্ভুক্ত করা হয়েছে যাতে NEWID () প্রতি সারি ভিত্তিতে নমুনা অর্জনের জন্য প্রতি সারিতে একবার মূল্যায়ন করে। CAST (CHECKSUM (NEWID (), SalesOrderID) & 0x7fffffff as float / 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

আপনি যদি টেবিলস্যাম্পল ব্যবহার করে পালাতে পারেন তবে এটি আপনাকে সেরা পারফরম্যান্স দেবে। অন্যথায় newid () / ফিল্টার পদ্ধতিটি ব্যবহার করুন। newid () / অর্ডার দ্বারা সর্বশেষ অবলম্বন হওয়া উচিত যদি আপনার একটি বড় ফলাফল সেট থাকে।


4

যদি সম্ভব হয় তবে আরএনডি () এবং উভয় সূচকের অদক্ষতা এড়াতে এবং রেকর্ড নম্বর ক্ষেত্র তৈরি করতে সঞ্চিত বিবরণ ব্যবহার করুন।

"টেবিলের সীমা থেকে সীমাবদ্ধ? * 1" থেকে র্যান্ডমরেকর্ডটি প্রস্তুত করুন;
SET @ n = ফ্লোর (RAND () * (সারণী থেকে COUNT (*) সারণী));
র‌্যান্ডম রেকর্ড ব্যবহার করুন @n;

উপরের ধারাটি সমানভাবে বিতরণ না করা হলে এই সমাধানটি এলোমেলো সারিগুলি ফিরিয়ে আনারও যত্ন নেয়; সুতরাং id_value> = RAND () * MAX (id_value) যেখানে ব্যবহার করার মতো প্রায় একই (ধ্রুবক) সময় লাগে তা আরও ভাল।
গাইডো

আমি যতদূর বলতে পারি এটি স্থির সময়ে চলবে না, এটি লিনিয়ার সময়ে চলে। সবচেয়ে খারাপ ক্ষেত্রে, @n টেবিলের সারি সংখ্যার সমান এবং "সারণি * সারণী থেকে সীমাবদ্ধ সীমাবদ্ধ?? 1" @n - 1 টি সারিটি শেষের দিকে না আসা পর্যন্ত মূল্যায়ন করে।
আন্দ্রেস রিওফ্রিও

3

সেরা উপায়টি কেবলমাত্র সেই উদ্দেশ্যে একটি নতুন কলামে একটি এলোমেলো মান স্থাপন করা এবং এর মতো কিছু ব্যবহার করা (সিউড কোড + এসকিউএল):

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

এটি মিডিয়াউইকি কোড দ্বারা নিযুক্ত সমাধান। অবশ্যই, ছোট মানগুলির বিরুদ্ধে কিছু পক্ষপাত রয়েছে, তবে তারা দেখতে পেয়েছিল যে কোনও সারি আনার সময় এলোমেলো মান শূন্যের কাছাকাছি আবৃত করার পক্ষে এটি যথেষ্ট ছিল।

newid () সমাধানের জন্য পুরো টেবিল স্ক্যানের প্রয়োজন হতে পারে যাতে প্রতিটি সারিতে একটি নতুন নির্দেশিকা নির্ধারিত করা যায়, যা অনেক কম পারফরম্যান্ট হবে।

র্যান্ড () সমাধান কিছুতেই কাজ করতে পারে না (যেমন এমএসএসকিউএল সহ) কারণ ফাংশনটি একবারে মূল্যায়ন করা হবে এবং প্রতিটি সারিতে একই "এলোমেলো" নম্বর বরাদ্দ করা হবে।


1
যখন আপনি 0 ফলাফল পাবেন তখন চারদিকে মোড়ানো একটি কার্যকরভাবে এলোমেলো নমুনা সরবরাহ করে (কেবল "যথেষ্ট ভাল" নয়)। এই সমাধানটি প্রায় একাধিক সারি ক্যোয়ারিতে স্কেল করে ("পার্টি শিফল" মনে করুন)। সমস্যাটি হ'ল ফলাফলগুলি একই গ্রুপে বারবার নির্বাচিত হতে থাকে। এটি পেতে, আপনাকে সবেমাত্র ব্যবহার করা এলোমেলো সংখ্যা পুনরায় বিতরণ করতে হবে। আপনি এলোমেলো কোনও ট্র্যাক রেখে এবং ফলাফল থেকে সর্বোচ্চ (এলোমেলোভাবে) সেট করে প্রতারণা করতে পারেন, তবে তারপরে পি (ক্যোয়ারিতে 1 সারি এবং i ক্যোয়ারিতে 2 সারি) == 0, যা ন্যায্য নয়। আমাকে কিছু গণিত করুন, এবং আমি আপনার কাছে সত্যিকারের ন্যায্য স্কিম নিয়ে ফিরে আসব।
alsuren

3

এসকিউএল সার্ভার ২০০ 2005 এবং ২০০৮ এর জন্য, যদি আমরা স্বতন্ত্র সারিগুলির একটি এলোমেলো নমুনা চাই ( অনলাইন বই থেকে ):

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

3

এর Insted , এ এন ডি () ব্যবহার করে যেমন উৎসাহিত করা হয় না , আপনি কেবল সর্বোচ্চ আইডি (= সর্বোচ্চ) পেতে পারেন:

SELECT MAX(ID) FROM TABLE;

১. এর মধ্যে একটি র্যান্ডম পান (মাই_জেনারেটেড_র্যান্ডম)

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

নোট করুন যে এটি যে কোনও সারিগুলির জন্য যাচাই করবে যা পছন্দসই মানের তুলনায় আইডিয়াল EQUAL বা উচ্চতর। টেবিলের নিচে সারিটি অনুসন্ধান করা এবং My_Genrated_Random এর চেয়ে সমান বা কম আইডি পাওয়া সম্ভব, তারপরে কোয়েরিটি এইরকম পরিবর্তন করুন:

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

উত্পাদিত এলোমেলো আইডি টেবিলটিতে আর উপস্থিত না থাকলে কী হবে? মুছে ফেলা বা নিষ্ক্রিয় সারিগুলি যা আপনি ব্যবহারকারীকে দেখাতে চান না তা সমস্যার কারণ হতে পারে।
এবেলমে

কিছুই নেই। আপনি ক্লোজস্ট পাবেন, সঠিক নয়, আইডি নম্বর। আপনি যদি আইডি = 1 সরিয়ে ফেলা বিবেচনা করেন তবে সর্বনিম্ন 1 দিয়ে বিনিময় করুন।
forsberg

2

@ সিএনএনউর উত্তর সম্পর্কে @ বিলকারভিনের মন্তব্যে যেমন উল্লেখ করা হয়েছে ...

কোনও সীমাবদ্ধতার সাথে সংমিশ্রণের সময়, আমি দেখতে পেয়েছি যে এটি আসল সারিগুলি সরাসরি অর্ডার না করে এলোমেলো ক্রমবর্ধমান যুক্ত হয়ে (কমপক্ষে পোস্টগ্র্যাসকিউএল 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

কেবলমাত্র নিশ্চিত হয়ে নিন যে 'আর' জটিল জটিল ক্যোয়ারিতে প্রতিটি সম্ভাব্য মূল্যের জন্য একটি 'র্যান্ড' মান উত্পন্ন করে তবে এটি যেখানে সম্ভব সেখানে 'আর' এর সারিগুলির সংখ্যা সীমাবদ্ধ করে।

পূর্ণসংখ্যা হিসাবে CAST বিশেষত PostgreSQL 9.2 এর জন্য সহায়ক যা পূর্ণসংখ্যা এবং একক নির্ভুলতা ভাসমান প্রকারের জন্য নির্দিষ্ট সাজানোর অপ্টিমাইজেশন রয়েছে।


1

এখানে বেশিরভাগ সমাধানগুলি বাছাই করা এড়াতে লক্ষ্য করে, তবে তাদের এখনও একটি টেবিলের উপর ক্রমিক স্ক্যান করা দরকার need

ইনডেক্স স্ক্যানে পরিবর্তন করে সিক্যুয়াল স্ক্যান এড়ানোরও একটি উপায় রয়েছে। যদি আপনি নিজের এলোমেলো সারির সূচক মান জানেন তবে আপনি প্রায় তাত্ক্ষণিকভাবে ফলাফল পেতে পারেন। সমস্যাটি হ'ল কীভাবে সূচকের মান অনুমান করা যায়।

নিম্নলিখিত সমাধান 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

দেরীতে, তবে গুগলের মাধ্যমে এখানে পৌঁছেছে, সুতরাং উত্তরোত্তর জন্য, আমি একটি বিকল্প সমাধান যুক্ত করব।

আরেকটি পদ্ধতির বিকল্প অর্ডার সহ শীর্ষে দু'বার ব্যবহার করা। এটি "খাঁটি এসকিউএল" কিনা তা আমি জানি না, কারণ এটি শীর্ষে একটি চলক ব্যবহার করে তবে এটি এসকিউএল সার্ভার ২০০৮ এ কাজ করে dictionary

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

অবশ্যই, @ আইডিএক্স হ'ল কিছু এলোমেলোভাবে উত্পন্ন পূর্ণসংখ্যা যা লক্ষ্য টেবিলটিতে 1 থেকে COUNT (*) অবধি অন্তর্ভুক্ত। যদি আপনার কলামটি সূচিযুক্ত হয় তবে আপনি এটি থেকেও উপকৃত হবেন। আরেকটি সুবিধা হ'ল আপনি এটি কোনও ফাংশনে ব্যবহার করতে পারবেন, যেহেতু NEWID () অনুমোদিত নয়।

শেষ অবধি, উপরের ক্যোয়ারীটি একটি নতুন টেবিলে () সম্পাদনার সময়টির প্রায় 1/10-এ চলেছে - একই টেবিলে কোয়েরির ধরণ। YYMV।


1

আপনি new id()ফাংশন ব্যবহার করার চেষ্টা করতে পারেন ।

কেবল আপনার ক্যোয়ারী লিখুন এবং new id()ফাংশন অনুসারে অর্ডার ব্যবহার করুন । এটি বেশ এলোমেলো।


1

মাইএসকিউএল এলোমেলো রেকর্ড পেতে

 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/


অনেক উত্তর পরীক্ষার পরে আমি বিশ্বাস করি যে এটি সেরা this এটি দ্রুত বলে মনে হচ্ছে এবং প্রতিবার একটি ভাল এলোমেলো সংখ্যা তুলে ধরে। এটি উপরের @ গ্রেপ্যান্থারের দ্বিতীয় পরামর্শের মতো বলে মনে হচ্ছে তবে এই উত্তরটি আরও এলোমেলো সংখ্যা বেছে নিয়েছে।
জেফ বাকের

1

উত্তরের ক্ষেত্রে এই প্রকরণটি বেশিরভাগভাবে দেখেনি। প্রতিবার একই সারির একই সেট নির্বাচন করতে আমার প্রাথমিক বাধা দেওয়াতে আমার অতিরিক্ত বাধা ছিল।

এমএস এসকিউএল এর জন্য:

সর্বনিম্ন উদাহরণ:

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

এমএসএসকিউএলে (11.0.5569 এ পরীক্ষিত) ব্যবহার করে

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

তুলনায় উল্লেখযোগ্যভাবে দ্রুত

SELECT TOP 100 * FROM employee ORDER BY NEWID()

1

এসকিউএল সার্ভারে আপনি টেবিলসাম্পলকে NEWID () এর সাথে একত্রিত করতে পারেন বেশ ভাল এলোমেলোতা পেতে এবং এখনও গতি আছে। এটি বিশেষত কার্যকর যদি আপনি সত্যিই কেবল 1 বা কম সংখ্যক সারি চান।

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

1

এসকিউএল সার্ভারের সাথে 2012+ আপনি ব্যবহার করতে পারেন OFFSET ক্যোয়ারী আনা একটি একক র্যান্ডম সারিতে এই কাজ করতে

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

যেখানে আইডি হ'ল একটি পরিচয় কলাম, এবং n আপনার সারিটি চান - টেবিলের 0 এবং গণনা () - 1 এর মধ্যে একটি এলোমেলো সংখ্যা হিসাবে গণনা করা হয় (অফসেট 0 সর্বোপরি প্রথম সারিতে থাকবে)

এটি সারণীর ডেটাগুলির গর্তগুলির সাথে কাজ করে, যতক্ষণ না আপনার অর্ডারের বিধি অনুসারে কাজ করার জন্য একটি সূচক থাকে। এটি এলোমেলোতার জন্যও খুব ভাল - আপনি যেমন কাজ করেন যে আপনি নিজের মধ্যে প্রবেশ করতে পারেন তবে অন্যান্য পদ্ধতিতে নিগলগুলি উপস্থিত নেই। এছাড়াও পারফরম্যান্সটি বেশ ভাল, একটি ছোট ডেটাসেটে এটি ভালভাবে ধরেছে, যদিও আমি কয়েক মিলিয়ন সারিগুলির বিরুদ্ধে গুরুতর পারফরম্যান্স পরীক্ষার চেষ্টা করিনি।



0

আমাকে সিডি-ম্যানের সাথে একমত হতে হবে: "অর্ডার বাই র‌্যান্ড ()" ব্যবহার করে ছোট টেবিলের জন্য বা আপনি যখন কয়েকবার আপনার নির্বাচন করবেন তখন দুর্দান্তভাবে কাজ করবে।

আমি "num_value> = RAND () * ..." কৌশলটিও ব্যবহার করি এবং আমি যদি সত্যিই এলোমেলো ফলাফল পেতে চাই তবে আমার টেবিলে একটি বিশেষ "এলোমেলো" কলাম রয়েছে যা আমি দিনে বা একদিন একবার আপডেট করি। সেই একক আপডেটের রানটি কিছুটা সময় নেবে (বিশেষত কারণ আপনাকে column কলামটিতে একটি সূচি থাকতে হবে), তবে প্রতিবারের জন্য প্রতিটি বারের জন্য নির্বাচনটি নির্বাচন করার সময় এলোমেলো সংখ্যা তৈরি করা অনেক দ্রুত faster


0

সতর্কতা অবলম্বন করুন কারণ টেবিল নমুনা আসলে সারিগুলির একটি এলোমেলো নমুনা দেয় না। এটি আপনার সন্ধানটি 8 কেবি পৃষ্ঠাগুলির একটি এলোমেলো নমুনা সন্ধান করার নির্দেশ দেয় যা আপনার সারিটি তৈরি করে। তারপরে, আপনার প্রশ্নগুলি এই পৃষ্ঠাগুলিতে থাকা ডেটার বিপরীতে কার্যকর করা হবে। এই পৃষ্ঠাগুলিতে ডেটা কীভাবে গোষ্ঠীভুক্ত করা যেতে পারে (সন্নিবেশনের ক্রম, ইত্যাদি) এর ফলে এটি এমন ডেটার দিকে নিয়ে যেতে পারে যা আসলে এলোমেলো নমুনা নয়।

দেখুন: http://www.mssqltips.com/tip.asp?tip=1308

টেবিলসাম্পলের জন্য এই এমএসডিএন পৃষ্ঠাতে কীভাবে উপাত্তের সত্যতা র্যান্ডম নমুনা তৈরি করা যায় তার একটি উদাহরণ অন্তর্ভুক্ত রয়েছে।

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


0

দেখে মনে হচ্ছে তালিকাভুক্ত অনেকগুলি ধারণা এখনও ক্রম ব্যবহার করে

তবে, আপনি যদি একটি অস্থায়ী টেবিল ব্যবহার করেন তবে আপনি একটি এলোমেলো সূচী নির্ধারণ করতে সক্ষম হবেন (সমাধানের অনেকগুলি পরামর্শের মতো) এবং তারপরে প্রথমটি ধরুন যা 0 এবং 1 এর মধ্যে একটি স্বেচ্ছাসেবী সংখ্যার চেয়ে বেশি।

উদাহরণস্বরূপ (ডিবি 2 এর জন্য):

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% সম্ভাবনা রয়েছে যে সেই মানদণ্ডটি পূরণ করবে meet
ডেভিড


0

Dbms_random.value ব্যবহার না করে ওরাকল এর জন্য আরও ভাল সমাধান রয়েছে, যখন dbms_random.value দ্বারা সারি অর্ডার করার জন্য এটি সম্পূর্ণ স্ক্যানের প্রয়োজন এবং এটি বড় টেবিলগুলির জন্য বেশ ধীরে ধীরে।

পরিবর্তে এটি ব্যবহার করুন:

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

0

ফায়ারবার্ডের জন্য:

Select FIRST 1 column from table ORDER BY RAND()

0

এসকিউএল সার্ভার ২০০৫ এবং তারপরের জন্য, যখন 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
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.