Как случайным образом выбрать строки в SQL?

Я использую MSSQL Server 2005. В моей БД у меня есть таблица "customerNames", которая имеет два столбца "Id" и "Name" и прибл. 1000 результатов.

Я создаю функциональность, где я должен выбрать 5 клиентов случайным образом каждый раз. Может ли кто-нибудь сказать мне, как создать запрос, который будет получать случайные 5 строк (Id и Name) каждый раз при выполнении запроса?

9 ответов


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 Server:

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

выбрать случайную запись с Оракул:

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

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

если кому-то нужно решение PostgreSQL:

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

может быть этот сайт будет помощи.

для тех, кто не хочет нажимать:

SELECT TOP 1 column FROM table
ORDER BY NEWID()

здесь есть хорошее решение Microsoft SQL Server 2005. Имеет дело с проблемой, когда вы работаете с большим набором результатов (не вопрос, который я знаю).

выбор строк случайным образом из большой таблицы http://msdn.microsoft.com/en-us/library/cc441928.aspx


Я нашел, что это лучше всего работает для больших данных.

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

TABLESAMPLE(n ROWS) or TABLESAMPLE(n PERCENT) является случайным, но нужно добавить TOP n чтобы получить правильный размер образца.

используя NEWID() очень медленно на больших таблицах.


SELECT * FROM tableName ORDER BY random () LIMIT 5;


Если у вас есть таблица с миллионами строк и заботятся о производительности, это может быть лучший ответ:

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

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


Это старый вопрос, но попытка применить новое поле (NEWID() или ORDER BY rand()) к таблице с большим количеством строк будет непомерно дорогой. Если у вас есть инкрементные, уникальные идентификаторы (и не имеют отверстий), будет более эффективно вычислить X # идентификаторов, которые будут выбраны вместо применения GUID или аналогичного каждой отдельной строке, а затем принимая верхний X#.

DECLARE @maxValue int = (select max(id) from [TABLE])
DECLARE @minValue int = (select min(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 с идентификатором и кучей значений rand (), затем используя каждое значение rand () для масштабирования до значений min-max. Таким образом, вам не нужно определять все @randomId1...параметры N. Я включил пример ниже, используя cte для заполнения начальной таблицы.

DECLARE @NumItems int = 100;

DECLARE @maxValue int = (select max(id) from [TABLE])
DECLARE @minValue int = (select min(id) from [TABLE])

with cte (n) as (select 1 union all select n+1 from cte where n < @NumItems)
select cast( ((@maxValue + 1) - @minValue) * rand(cast(newid() as varbinary(100))) + @minValue as int) as tp into #Nt
from 
cte
select * from  #Nt ntt
inner join [TABLE] i 
        on i.id = ntt.tp
drop table #Nt