Что я делаю неправильно при использовании RAND () в MS SQL Server 2005?

Я пытаюсь выбрать случайную 10% выборку из небольшой таблицы. Я думал, что просто воспользуюсь функцией RAND () и выберу те строки, в которых случайное число меньше 0,10:

SELECT * FROM SomeTable
WHERE SomeColumn='SomeCondition' AND
      RAND() < 0.10

Но вскоре я обнаружил, что RAND () всегда возвращает одно и то же число! Напоминает мне этот xkcd мультфильм.

Что я делаю неправильно при использовании RAND () в MS SQL Server 2005?

Хорошо, без проблем, функция RAND принимает начальное значение. Я буду запускать этот запрос периодически, и я хочу, чтобы он давал разные результаты, если я запустил его в другой день, поэтому я заполняю его комбинацией даты и уникального идентификатора строки:

SELECT * FROM SomeTable
WHERE SomeColumn='SomeCondition' AND
      RAND(CAST(GETDATE) AS INTEGER) + RowID) < 0.10

Я все еще не получаю результатов! Когда я показываю случайные числа, возвращаемые RAND, я обнаруживаю, что все они находятся в узком диапазоне. Похоже, что получение случайного числа из RAND требует, чтобы вы использовали случайное начальное число. Если бы у меня изначально было случайное семя, мне бы не понадобилось случайное число!

Я видел предыдущие обсуждения, связанные с этой проблемой:

Случайная сортировка SQL Server
Как запросить случайную строку в SQL?

Они мне не помогают. TABLESAMPLE работает на уровне страницы, что отлично подходит для большой таблицы, но не для маленькой, и похоже, что это применяется до предложения WHERE. TOP с NEWID не работает, потому что я не знаю заранее, сколько строк мне нужно.

У кого-нибудь есть решение или хотя бы подсказка?

Редактировать: Спасибо AlexCuse за решение, который работает в моем конкретном случае. Теперь перейдем к более важному вопросу: как заставить работать RAND?

ReactJs | Supabase | Добавление данных в базу данных
ReactJs | Supabase | Добавление данных в базу данных
Это и есть ваш редактор таблиц в supabase.👇
Понимание Python и переход к SQL
Понимание Python и переход к SQL
Перед нами лабораторная работа по BloodOath:
3
0
3 544
5
Перейти к ответу Данный вопрос помечен как решенный

Ответы 5

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

SELECT * FROM SomeTable WHERE SomeColumn='SomeCondition' AND 0*rowid+RAND() < 0.10

Чтобы оценить RAND() один раз для каждая строка, а не один раз в начало вашего запроса.

Виноват оптимизатор запросов. Возможно, есть другой способ, но я верю, что он сработает для вас.

Этот метод у меня не работает. У меня есть только varchar и int, и я не понимаю, почему int будет вести себя иначе, чем numeric.

Mark Ransom 02.10.2008 21:48

Если это оптимизатор, то это очень похоже на мультик!

Ken 02.10.2008 21:51

Возможно, это моя вина, но говоря «числовой», я имел в виду любой числовой тип (целое, краткое, с плавающей запятой, числовой «SQL» и т. д.). Пожалуйста, проверьте мой ответ еще раз.

tzot 02.10.2008 21:59
Ответ принят как подходящий

Такой подход (обозначенный знаком ΤΖΩΤΖΙΟΥ) не гарантирует 10% выборки. Он предоставит вам только все строки, в которых Rand () оценивается как <0,10, что не будет согласованным.

Что-то типа

select top 10 percent * from MyTable order by NEWID()

сделает свое дело.

редактировать: на самом деле нет хорошего способа заставить работать RAND. Это то, что я использовал в прошлом (предупреждение kludge - это убивает вас, когда вы не можете использовать Rand () в UDF)

CREATE VIEW RandView AS 

SELECT RAND() AS Val

GO

CREATE FUNCTION RandomFloat()
RETURNS FLOAT
AS
BEGIN

RETURN (SELECT Val FROM RandView)

END

Тогда у вас просто select blah, dbo.RandomFloat() from table в вашем запросе.

Мне было достаточно приближения к 10%, но ваш ответ прекрасно решает мою непосредственную проблему. Я должен был подумать проверить предложение PERCENT в TOP.

Mark Ransom 02.10.2008 22:42

Вы видели этот вопрос?

Как мне вернуть случайные числа в виде столбца в SQL Server 2005?

Адам опубликовал UDF, который можно использовать вместо Rand (), который работает намного лучше.

Кажется, это работает:

select * from SomeTable
where rand(0*SomeTableID + cast(cast(newid() as binary(4)) as int)) <= 0.10

Кажется, это работает

SELECT TOP 10 PERCENT * FROM schema.MyTable ORDER BY NEWID()

Другие вопросы по теме