Ответ 1
Я понимаю, что это более старое сообщение... но вам не нужно представление.
select column1, column2,
ABS(CAST(CAST(NEWID() AS VARBINARY) AS int)) % 10000 as column3
from table1
Я запускаю SQL-запрос на SQL Server 2005, и помимо двух столбцов, запрашиваемых из базы данных, я также хотел бы вернуть 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)
Трассировка профилировщика:
alt text 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, содержащая функцию, которая возвращает случайное число
Query
select column1, column2, cast(new_id() as varchar(10)) as column3
from table1
Вам может потребоваться генерировать UUID вместо случайного числа, используя новую функцию. Они гарантированно будут уникальными каждый раз, когда генерируется, тогда как существует значительная вероятность того, что некоторое дублирование произойдет с простым случайным числом (и в зависимости от того, для чего вы его используете, может дать вам феноменально трудно отладить ошибку в более поздней точке)
newid() Я считаю, что это очень ресурсоемкий. я помню, как пытался этот метод на таблице из нескольких миллионов записей, а производительность была не так хороша, как rand().
Согласно моему тестированию, ответ выше не генерирует значение 10000 когда-либо. Это, вероятно, не является большой проблемой при генерации случайного значения от 1 до 10000, но тот же алгоритм между 1 и 5 будет заметным. Добавьте 1 в свой мод.
Этот фрагмент, по-видимому, обеспечивает разумную замену rand()
тем, что он возвращает float между 0.0 и 1.0. Он использует только последние 3 байта, предоставленные newid()
, поэтому полная случайность может несколько отличаться от преобразования в VARBINARY
, затем INT
, а затем modding из рекомендуемого ответа. У меня не было возможности проверить относительную производительность, но я считаю достаточно быстрым (и достаточно случайным) для своих целей.
SELECT CAST(SubString(CONVERT(binary(16), newid()), 14, 3) AS INT) / 16777216.0 AS R
Я использую С# для обработки случайных чисел. Это намного чище. У меня есть функция, которую я использую, чтобы вернуть список случайных чисел и уникальный ключ, после чего я просто присоединяюсь к уникальному ключу по номеру строки. Поскольку я использую С#, я могу легко указать диапазон, в пределах которого должны выпадать случайные числа.
Вот шаги по созданию функции: 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