SQL Server выбирает случайный И не случайный - PullRequest
2 голосов
/ 10 ноября 2011

У меня есть одна таблица, и я хочу выбрать 10 строк случайным образом. Но мне также нужно выбрать любые строки, которые находятся в «продаже». Я хочу только 10 строк, может быть 2 строки продажи, может быть 9, мне нужно заполнить оставшиеся случайными строками. Мне нужен один запрос.

SELECT TOP 10 BookTitle, BookAuthor, BookCategory
FROM TheTable
ORDER BY newid()

SELECT TOP 10 BookTitle, BookAuthor, BookCategory
FROM TheTable
WHERE BookCategory LIKE 'Sale%' 

Я продолжаю вычеркивать, Я, может быть, слишком или недооцениваю это ...

Спасибо.

Ответы [ 4 ]

4 голосов
/ 10 ноября 2011

Выберите 10 по категориям и 10 случайных в подзапросе.
Расставьте приоритеты по категориям.

SELECT TOP 10 BookTitle, BookAuthor, BookCategory
FROM (
    SELECT TOP 10 BookTitle, BookAuthor, BookCategory, 0 as prio
    FROM TheTable
    WHERE BookCategory LIKE 'Sale%')

    UNION ALL 
    SELECT TOP 10 BookTitle, BookAuthor, BookCategory, 1 As prio
    FROM TheTable
    TABLESAMPLE (50 ROWS)
    ) x
ORDER BY prio

Я взял TABLESAMPLE из ответа @ Remus, потому что это, очевидно, намного быстрее сбольшие столы.Голосуйте за него, если это главная особенность для вас.

Однако , я настроил его TABLESAMPLE (50 ROWS), из-за этого предупреждения в руководстве :

Фактическое количество строк, которыевозвращены могут значительно различаться.Если вы укажете небольшое число, например 5, вы можете не получить результаты в образце.

Я только что проверил и воспроизвел это.Я оставил TOP 10 дополнительно, потому что в конце концов нам нужно максимум 10.

Кроме того, руководство добавляет дискламер к «случайности»:

Если вам действительно нужна случайная выборка отдельных строк, измените запрос, чтобы отфильтровать строки случайным образом, вместо использования TABLESAMPLE.

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

4 голосов
/ 10 ноября 2011

Не очень эффективно для большого стола, но ...

SELECT TOP 10 BookTitle,
              BookAuthor,
              BookCategory
FROM   TheTable
ORDER  BY CASE
            WHEN BookCategory LIKE 'Sale%' THEN 0
            ELSE 1
          END,
          newid()  

Если ваша таблица большая, вам, вероятно, следует выполнить 2 запроса. Один, чтобы получить предметы для продажи, а затем второй, чтобы получить «случайное» количество случайных не продаваемых предметов, только если требуется.

2 голосов
/ 10 ноября 2011

Используйте TABLESAMPLE.Использование наивного подхода ORDER BY NEWID() приведет к ужасной производительности, поскольку всю таблицу придется сканировать и упорядочивать для каждого запроса, просто чтобы выбрать 10 случайных строк.Встроенный синтаксис TABLESAMPLE даст желаемое количество строк с помощью высокоэффективной выборки страниц ввода-вывода, а случайность выборки более чем достаточна для повседневного использования.См. Ограничение наборов результатов с помощью TABLESAMPLE для получения более подробной информации.

select top(10) BookTitle, BookAuthor, BookCategory 
from (
   SELECT TOP(10) BookTitle, BookAuthor, BookCategory
   FROM TheTable
   WHERE BookCategory LIKE 'Sale%'
   UNION ALL 
   SELECT BookTitle, BookAuthor, BookCategory
   FROM TheTable TABLESAMPLE (10 ROWS)) as theUnion;

Обратите внимание, что это не гарантирует, что любая «случайная» строка не является одной из строк «Sale%»,производя в действительности дубликаты.Если вам требуется такое исключение, это возможно, но более сложно и потенциально неэффективно.

0 голосов
/ 10 ноября 2011

Что-то не так с объединением обоих запросов?

SELECT TOP 10 BookTitle, BookAuthor, BookCategory
FROM TheTable
ORDER BY newid()
WHERE BookCategory LIKE 'Sale%'
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...