Перша пропозиція Pradeep Adiga ORDER BY NEWID()
, - це добре, і я щось використовував у минулому з цієї причини.
Будьте обережні з використанням RAND()
- у багатьох контекстах воно виконується лише один раз за оператором, тому ORDER BY RAND()
не матиме ефекту (оскільки ви отримуєте однаковий результат з RAND () для кожного рядка).
Наприклад:
SELECT display_name, RAND() FROM tr_person
повертає кожне ім’я з нашої таблиці особи та "випадкове" число, яке однакове для кожного рядка. Кількість змінюється щоразу при запуску запиту, але однакова для кожного рядка кожен раз.
Щоб показати, що те саме стосується і RAND()
використовуваного в ORDER BY
пункті, я намагаюся:
SELECT display_name FROM tr_person ORDER BY RAND(), display_name
Результати все ще упорядковані назвою, що вказує на те, що поле раннього сортування (те, що очікується випадковим) не має ефекту, тому, імовірно, завжди має однакове значення.
NEWID()
Однак впорядкування працює, тому що, якщо NEWID () не завжди був переоцінений, мета UUID буде порушена при введенні багатьох нових рядків в один документ з унікальними ідентифікаторами, як вони вводять, так:
SELECT display_name FROM tr_person ORDER BY NEWID()
робить замовлення імен «випадкові».
Інші СУБД
Сказане стосується MSSQL (принаймні, 2005 та 2008 рр., І якщо я добре пам’ятаю 2000 р.). Функція, що повертає новий UUID, повинна оцінюватися кожного разу, коли всі СУБД NEWID () знаходиться під MSSQL, але варто перевірити це в документації та / або власними тестами. Поведінка інших функцій довільного результату, таких як RAND (), швидше відрізняється між СУБД, тому ще раз перевірте документацію.
Також я бачив, що впорядкування за значеннями UUID в деяких контекстах ігнорується, оскільки БД передбачає, що тип не має значущого впорядкування. Якщо ви вважаєте, що це випадок, явно передавайте UUID на тип рядка в замовленні, або оберніть навколо нього якусь іншу функцію, як CHECKSUM()
у SQL Server (можливо, для цього буде невелика різниця в продуктивності, оскільки впорядкування буде здійснено на 32-розрядні значення не є 128-бітними, хоча перевага від цього переважає вартість запуску CHECKSUM()
за значенням спочатку я залишу вас перевірити).
Бічна примітка
Якщо ви хочете довільне, але дещо повторюване впорядкування, впорядкуйте за деяким відносно неконтрольованим набором даних у самих рядках. Наприклад, або вони повернуть імена в довільному, але повторюваному порядку:
SELECT display_name FROM tr_person ORDER BY CHECKSUM(display_name), display_name -- order by the checksum of some of the row's data
SELECT display_name FROM tr_person ORDER BY SUBSTRING(display_name, LEN(display_name)/2, 128) -- order by part of the name field, but not in any an obviously recognisable order)
Довільні, але повторювані замовлення не часто корисні в додатках, хоча можуть бути корисними для тестування, якщо ви хочете перевірити деякий код на результатах у різних замовленнях, але хочете мати можливість повторювати кожен запуск однаково кілька разів (для отримання середнього часу результати протягом декількох запусків або тестування того, що зроблене вами виправлення в коді усуває проблему або неефективність, попередньо виділену певним набором результатів введення, або просто для тестування того, що ваш код "стабільний", тобто щоразу повертає той самий результат якщо надіслані ті самі дані в заданому порядку).
Цей трюк також може бути використаний для отримання більш довільних результатів від функцій, які не дозволяють недетермінованих дзвінків на зразок NEWID () у своєму тілі. Знову ж таки, це не те, що може бути корисним у реальному світі, але може стати в нагоді, якщо ви хочете, щоб функція повертала щось випадкове, а "випадковий результат" є досить хорошим (але будьте уважні, пам'ятайте правила, які визначають коли оцінюються визначені користувачем функції, тобто, як правило, один раз у ряд, або результати можуть бути не такими, які ви очікуєте / вимагаєте).
Продуктивність
Як зазначає EBarr, з будь-яким із перерахованих вище можуть виникнути проблеми з ефективністю. Більше декількох рядків вам майже гарантовано бачити результат, виведений на tempdb, до того, як запитане число рядків буде прочитано в правильному порядку, а це означає, що навіть якщо ви шукаєте першу десятку, ви можете знайти повний індекс сканування (або ще гірше, сканування таблиці) відбувається разом з величезним блоком запису в tempdb. Для цього може бути життєво важливим, як і для більшості речей, орієнтуватися на реалістичні дані, перш ніж використовувати їх у виробництві.