TSQL случайных записей извлекает дубликаты - PullRequest
1 голос
/ 16 марта 2012

Я должен извлечь две случайные записи из таблицы. Я реализовал нечто подобное в хранимой процедуре:

    with tmpTable as(
        SELECT top 500 [columns I need]
              , row_number() over(order by [myColumn]) as rown
        FROM SourceTable
          JOIN [myJoin]
        WHERE [myCondition]
    )
    -- here I extract with an intervall of 10 records: 10, 20, 30, ..., 400, 410, ...
    select * from tmpTable where rown = (1 + FLOOR(50*RAND()))*10

Отлично работает, извлекает случайную запись из первых 500 записей из моего источника. Но когда sp вызывается из уровня представления (ASP.NET 4.0, SqlClient ADO.NET), одна и та же запись возвращается дважды. Обратите внимание, что эти два вызова независимы друг от друга.

Полагаю, это зависит от того, что sp вызывается дважды за несколько миллисекунд и что генератор случайных чисел создает одно и то же число. В процессе отладки дублирование не происходит: я полагаю, что из-за ручных шагов F10 требуется больше нескольких миллисекунд.

Как мне получить две разные записи?

EDIT

Ответ Ламака требует некоторых дополнительных деталей. Исходная таблица состоит из записей продуктов. Группы из примерно 10 записей отличаются друг от друга только по некоторым характеристикам (например, по цвету). Записи распределяются таким образом:

1 to 10: product 1
11 to 20: product 2
... and so on

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

1 Ответ

1 голос
/ 16 марта 2012

Если вы используете SQL Server, вы можете просто сделать следующее:

SELECT TOP 1 [columns I need]
FROM SourceTable
JOIN [myJoin]
ON [Something]
WHERE [MyCondition]
ORDER BY NEWID()

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

SELECT TOP 1 *
FROM (  SELECT [columns I need], ROW_NUMBER() OVER(PARTITION BY Product ORDER BY NEWID())  Corr
        FROM SourceTable
        JOIN [myJoin]
        ON [Something]
        WHERE [MyCondition]) A
WHERE Corr = 1
ORDER BY NEWID()

Хотя вы все еще можете выбрать запись, которая имеет тот же продукт, что и первая.

...