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

StackOverflow https://stackoverflow.com/questions/94906

Вопрос

Я запускаю SQL-запрос на SQL Server 2005, и в дополнение к 2 столбцам, запрашиваемым из базы данных, я также хотел бы вернуть 1 столбец случайных чисел вместе с ними.Я попробовал это:

select column1, column2, floor(rand() * 10000) as column3 
from table1

Это вроде как работает, но проблема в том, что этот запрос возвращает одно и то же случайное число в каждой строке.Это другое число каждый раз, когда вы запускаете запрос, но оно не меняется от строки к строке.Как я могу это сделать и получить новое случайное число для каждой строки?

Это было полезно?

Решение

Я понимаю, что это более старый пост...но вам не нужен вид из окна.

select column1, column2, 
  ABS(CAST(CAST(NEWID() AS VARBINARY) AS int)) % 10000 as column3 
from table1

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

ПРЕДУПРЕЖДЕНИЕ

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

Вместо этого вы могли бы использовать этот ответ.

Доказательство:

CREATE VIEW vRandNumber
AS
SELECT RAND() as RandNumber

go 

CREATE FUNCTION RandNumber()
RETURNS float
AS
  BEGIN
  RETURN (SELECT RandNumber FROM vRandNumber)
  END

go 

create table bigtable(i int)

go 

insert into bigtable 
select top 100000 1 from sysobjects  a
join sysobjects b on 1=1

go 

select cast(dbo.RandNumber() * 10000 as integer) as r into #t from bigtable 
-- CPU (1607) READS (204639) DURATION (1551)

go

select ABS(CAST(CAST(NEWID() AS VARBINARY) AS int)) % 10000 as r  into #t1 
from bigtable
-- Runs 15 times faster - CPU (78) READS (809) DURATION (99)

Трассировка профилировщика:

альтернативный текст http://img519.imageshack.us/img519/8425/destroydbxu9.png

Это доказательство того, что материал достаточно случаен для чисел от 0 до 9999

-- proof that stuff is random enough 
select avg(r) from #t
-- 5004
select STDEV(r) from #t
-- 2895.1999 

select avg(r) from #t1
-- 4992
select STDEV(r) from #t1
-- 2881.44 


select r,count(r) from #t
group by r 
-- 10000 rows returned 

select r,count(r) from #t1
group by r 
-- 10000 row returned 

Ответ Адама работает действительно хорошо, поэтому я пометил его как принятый.Однако, пока я ждал ответа, я также нашел эту запись в блоге с несколькими другими (чуть менее случайными) методами.Метод Кабоинга был одним из них.

http://blog.sqlauthority.com/2007/04/29/sql-server-random-number-generator-script-sql-query/

select RAND(CHECKSUM(NEWID()))

Вам нужно использовать UDF

Первый:

CREATE VIEW vRandNumber
AS
SELECT RAND() as RandNumber

второй:

CREATE FUNCTION RandNumber()
RETURNS float
AS
  BEGIN
  RETURN (SELECT RandNumber FROM vRandNumber)
  END

тест:

SELECT dbo.RandNumber(), *
FROM <table>

Приведенное выше заимствовано из Блог Джеффа о SQL Server

Для SQLServer есть несколько вариантов.
1.Цикл while для обновления пустого столбца одним случайным числом за раз
2.Сборка .net, содержащая функцию, возвращающую случайное число

Возможно, вы захотите сгенерировать UUID вместо случайного числа, используя функцию newid.Они гарантированно будут уникальными каждый раз, когда генерируются, тогда как существует значительная вероятность того, что некоторое дублирование произойдет с простым случайным числом (и в зависимости от того, для чего вы его используете, это может привести к феноменально сложной для отладки ошибке на более позднем этапе)

newid() я считаю, что это очень ресурсоемко.я помню, как пробовал этот метод на таблице из нескольких миллионов записей, и производительность была далеко не такой хорошей, как у rand().

Согласно моему тестированию, приведенный выше ответ никогда не генерирует значение 10000.Вероятно, это не такая уж большая проблема, когда вы генерируете случайное число от 1 до 10000, но тот же алгоритм от 1 до 5 был бы заметен.Добавьте 1 к своему моду.

Этот фрагмент, по-видимому, является разумной заменой rand() в том смысле, что он возвращает значение с плавающей точкой между 0.0 и 1.0.Он использует только последние 3 байта, предоставленные newid() таким образом, общая случайность может немного отличаться от преобразования в VARBINARY тогда INT затем моддинг из рекомендованного ответа.У меня не было возможности протестировать относительную производительность, но она кажется достаточно быстрой (и достаточно случайной) для моих целей.

SELECT CAST(SubString(CONVERT(binary(16), newid()), 14, 3) AS INT) / 16777216.0 AS R

Я использую c # для работы со случайными числами.Здесь намного чище.У меня есть функция, которую я использую для возврата списка случайных чисел и уникального ключа, затем я просто присоединяю uniqueKey к номеру строки.Поскольку я использую c #, я могу легко указать диапазон, в пределах которого должны попадать случайные числа.

Вот шаги по созданию функции:http://www.sqlwithcindy.com/2013/04/elegant-random-number-list-in-sql-server.html

Вот как в итоге выглядит мой запрос:

SELECT 
   rowNumber, 
   name, 
   randomNumber
FROM dbo.tvfRandomNumberList(1,10,100) 
INNER JOIN (select ROW_NUMBER() over (order by int_id) as 'rowNumber', name from client        
            )as clients
ON clients.rowNumber = uniqueKey

Запрос

select column1, column2, cast(new_id() as varchar(10)) as column3 
from table1
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top