2013-05-24 7 views
0

У меня возникла проблема со случайными значениями, генерируемыми для каждой строки в результирующем наборе в SQL Server 2008. Я нашел аналогичный вопрос here, но после реализации предлагаемого ответа я увидел такой же проблема как раньше. При выполнении запроса, который я привел ниже, кажется, что одни и те же значения иногда появляются в последовательных строках, хотя я призываю новый NEWID() с каждой строкой.sql server 2008 не генерирует случайное значение

DECLARE @Id int = 0 
DECLARE @Counter int = 1 
DECLARE @Value int 

CREATE TABLE #Table1 
(
id int identity(1,1) 
,Value int 
) 

WHILE @Counter < 100000 
BEGIN 
    INSERT INTO #Table1 (Value) 
    SELECT CAST(RAND(CHECKSUM(NEWID())) * 100000 as INT) 
    SET @Counter += 1 
END 

SET @Counter = 0 
WHILE @Counter < 5 
BEGIN 
    SELECT 
     @Value = T.Value 
     ,@Id = T.id 
    FROM #Table1 T 
    WHERE T.id = CAST(RAND(CHECKSUM(NEWID())) * 100000 as INT) + 1 + @Counter 

    IF @Id <> 0 
     SELECT @Value AS Value ,@Id as ID 
    SET @Counter += 1 
END 
DROP TABLE #Table1 

Если изменить INT к BIGINT, как это было предложено в ссылке я представил, ничего не решается, так что я не верю, что что это «переполнение» вопрос.

+0

Редактировать: На самом деле, я добавляю счетчик к оператору 'WHERE' здесь, поэтому это не может быть проблемой при генерации случайного числа, а, скорее, при обновлении переменных, правильно ли? – whobetter

+0

Вы никогда не устанавливаете @Id обратно на 0 после его отображения, поэтому он будет отображаться снова на следующей итерации цикла, если ничего не найдено. –

+0

Это не тот случай. Двойные строки происходят с идентификаторами и значениями, отличными от 0. Кроме того, @Id обновляется с помощью оператора select во время каждой итерации независимо от того, отображается ли она. – whobetter

ответ

0

Если взять расчет из избранных, я не получаю удвоенные строки:

DECLARE @Id int = 0 
DECLARE @Counter int = 1 
DECLARE @Value int 
-- new variable 
DECLARE @DERIVED INT 

CREATE TABLE #Table1 
(
id int identity(1,1) 
,Value int 
) 

WHILE @Counter < 100000 
BEGIN 
    INSERT INTO #Table1 (Value) 
    SELECT CAST(RAND(CHECKSUM(NEWID())) * 100000 as INT) 
    SET @Counter += 1 
END 

SET @Counter = 0 
WHILE @Counter < 5 
BEGIN 
--set here to remove calculation from the select 
    SET @DERIVED = CAST(RAND(CHECKSUM(NEWID())) * 100000 as INT) + 1 + @Counter; 
    SELECT 
     @Value = T.Value 
     ,@Id = T.id 
    FROM #Table1 T 
    WHERE T.id = @DERIVED 

    IF @Id <> 0 
     SELECT @Value AS Value ,@Id as ID; 
    SET @Counter += 1 
END 
DROP TABLE #Table1 

Я вижу дубликаты каждый раз с псевдослучайным генератором внутри избранного. Как ни странно, я получаю одинаковую частоту дубликатов в цикле вставки, независимо от того, выполняется ли вычисление внутри вставки ... select. Это может быть совпадением, поскольку мы имеем дело со случайно выбранным числом. Обратите также внимание, что, поскольку вы добавляете к псевдослучайному результату, результаты не являются технически дублирующими. Они являются нисходящими последовательностями:

11111 + 1 + 1 = 11113 
11110 + 1 + 2 = 11113 

Такой же общий результат, разные псевдослучайные результаты. Однако, если я изменю

CAST(RAND(CHECKSUM(NEWID())) * 100000 as INT) + 1 + @Counter 

в

CAST(RAND(CHECKSUM(NEWID())) * 100000 as INT) + @Counter + @Counter 

Я до сих пор последовательно получить дубликаты. Это означает, что оптимизатор может быть кешированием/повторным использованием значений, по крайней мере, при выборе. Я бы назвал это неправильным для вызова недетерминированной функции. Я получаю аналогичные результаты по 10.0.1600 и 10.50.1600 (RTM 2008 и RTR 2008R2).

+0

Джейсон, спасибо за ваши усилия. Я вижу те же результаты, что и вы. Я также смог устранить дубликаты, установив '@ Id' и' @Value NULL' после увеличения счетчика. Еще раз спасибо. – whobetter

Смежные вопросы