Случайная запись из таблицы базы данных (T-SQL)
есть ли краткий способ получить случайную запись из таблицы sql server?
Я хотел бы рандомизировать мои данные модульного теста, поэтому ищу простой способ выбрать случайный идентификатор из таблицы. На английском языке выбор будет " выбрать один идентификатор из таблицы, где идентификатор является случайным числом между самым низким идентификатором в таблице и самым высоким идентификатором в таблице."
Я не могу понять, как это сделать, не нужно запускать запрос, проверять значение null, а затем повторный запуск, если значение null.
идеи?
5 ответов:
есть ли краткий способ получить случайную запись из таблицы sql server?
да
SELECT TOP 1 * FROM table ORDER BY NEWID()
объяснение
A
NEWID()
генерируется для каждой строки, а затем таблица сортируется по ней. Возвращается первая запись (т. е. запись с "самым низким" GUID).Примечания
GUID генерируются как псевдослучайные числа начиная с версии четыре:
версия 4 UUID предназначен для генерации UUID из действительно случайных или псевдо-случайных чисел.
алгоритм выглядит следующим образом:
- установите два наиболее значимых бита (биты 6 и 7) clock_seq_hi_and_reserved до нуля и единицы соответственно.
- установите четыре наиболее значимых бита (биты с 12 по 15) поле time_hi_and_version для 4-битного номера версии из Раздел 4.1.3.
- установите все остальные биты в случайном порядке (или псевдо-случайно) выбран ценности.
-универсально уникальный идентификатор (UUID) Urn Namespace-RFC 4122
альтернатива
SELECT TOP 1 * FROM table ORDER BY RAND()
не будет работать так, как можно было бы подумать.RAND()
возвращает одно значение на запрос, таким образом, все строки будут иметь одинаковое значение.в то время как значения GUID являются псевдослучайными, вам понадобится лучший PRNG для более требовательных приложения.
стандартная производительность составляет менее 10 секунд около 1 000 000 строк - конечно, в зависимости от системы. Обратите внимание, что невозможно попасть в индекс, поэтому производительность будет относительно ограниченной.
на больших столах вы также можете использовать
TABLESAMPLE
для этого, чтобы избежать сканирования всей таблицы.SELECT TOP 1 * FROM YourTable TABLESAMPLE (1000 ROWS) ORDER BY NEWID()
The
ORDER BY NEWID
по-прежнему требуется, чтобы избежать просто возвращать строки, которые появляются первыми на странице данных.число для использования должно быть тщательно выбрано для размера и определения таблицы, и вы можете рассмотреть логику повтора, если строка не возвращается. Математика за этим и почему техника не подходит для небольших таблиц является здесь обсуждается
также попробуйте свой метод, чтобы получить случайный идентификатор между MIN (Id) и MAX(Id), а затем
SELECT TOP 1 * FROM table WHERE Id >= @yourrandomid
Он всегда будет получать вам одну строку.
Если вы хотите выбрать большие данные, лучший способ, что я знаю:
SELECT * FROM Table1 WHERE (ABS(CAST( (BINARY_CHECKSUM (keycol1, NEWID())) as int)) % 100) < 10
источник: MSDN
Я искал, чтобы улучшить методы, которые я пробовал и наткнулся на этот пост. Я понимаю, что это старый, но этот метод не указан. Я создаю и применяю тестовые данные; это показывает метод для "адреса" в SP, вызываемом с @st (два состояния char)
Create Table ##TmpAddress (id Int Identity(1,1), street VarChar(50), city VarChar(50), st VarChar(2), zip VarChar(5)) Insert Into ##TmpAddress(street, city, st, zip) Select street, city, st, zip From tbl_Address (NOLOCK) Where st = @st -- unseeded RAND() will return the same number when called in rapid succession so -- here, I seed it with a guaranteed different number each time. @@ROWCOUNT is the count from the most recent table operation. Set @csr = Ceiling(RAND(convert(varbinary, newid())) * @@ROWCOUNT) Select street, city, st, Right(('00000' + ltrim(zip)),5) As zip From ##tmpAddress (NOLOCK) Where id = @csr