SQL-запрос для случайных 10% с минимумом 20 строк - PullRequest
0 голосов
/ 01 февраля 2019

Мне было поручено создать отчет, который будет случайным образом выбирать 10% уникального идентификатора, если только 10% не будет меньше 20 пунктов, в этом случае в отчете будут выбраны 20 случайных идентификаторов.Я использовал NewID, чтобы сгенерировать 10%, но это на самом деле не самое лучшее, поскольку оно дает мне переменные результаты (IE: больше или меньше 10%)

Код также включает мои попытки получитьобщее количество результатов:

select  UniqueID, TotalCount = Count(*) Over(), SUM(COUNT(UniqueID)) OVER() 
AS total_count 
from table 
where 0.15 >= CAST(CHECKSUM(NEWID(), UniqueID) & 0x7fffffff AS float) / CAST (0x7fffffff AS int)
group by UniqueID

Ответы [ 4 ]

0 голосов
/ 02 февраля 2019

Если в вашей таблице было UniqueID, где COUNT(UniqueID) было больше 1 (на UniqueID), то UniqueID не было уникальным , поэтомуСтолбцы TotalCount и total_count в вашем запросе должны возвращать одинаковые значения.

Чтобы отфильтровать первые 10 процентов (или не менее 20) ваших записей, вы можете вычислить случайное число строк (используя NEWID()) и примените к нему фильтр (включая общее количество записей).Как номер строки, так и общее количество записей можно рассчитать, используя оконные функции (с предложением OVER), но поскольку эти функции нельзя использовать в предложении WHERE (они предоставляют дополнительную информацию после обычногонабор результатов был сгенерирован), вычисление должно выполняться в подзапросе (который может быть записан как CTE).Я предлагаю попробовать это так:

WITH
  cte AS (
    SELECT UniqueID,
      RowNumber = ROW_NUMBER() OVER (ORDER BY NEWID()),
      MaxNumber = COUNT(*) OVER ()
    FROM YourTable
  )
SELECT UniqueID
FROM cte
WHERE RowNumber <= MaxNumber/10 OR RowNumber <= 20;

Если вам нужно округлить 10% -ное значение для дробных значений (как это делает TOP x PERCENT), попробуйте альтернативное предложение WHERE:

WHERE RowNumber <= (MaxNumber+9)/10 OR RowNumber <= 20;
0 голосов
/ 01 февраля 2019
if ((select count (*) as a from (select top 10 percent * from  [table]) t) < 20)
BEGIN
Select top 20 * from [table] order by newid()
END 
ELSE 
BEGIN
select top 10 percent * from  [table] order by newid() END
0 голосов
/ 01 февраля 2019

Если вам не нужно знать общее количество строк, то приведенная ниже конструкция, вероятно, является самым быстрым подходом для вашего требования «10% или первые 20»

If (SELECT COUNT(*) FROM (
      SELECT TOP 200 *  -- if 10% = 20, then 100% = 200
      FROM [table]       ) AS top200
   ) < 200
BEGIN
  SELECT TOP 20 ...
END
ELSE
BEGIN
  SELECT TOP 10 PERCENT ...
END

Обратите внимание, что нетORDER BY во внутреннем запросе

0 голосов
/ 01 февраля 2019

Я бы сгенерировал row_number, упорядоченный по new_id, а затем выяснил, сколько (N) из строк, которые вы можете взять (строки 1 ...... N), должно быть случайным.если у вас меньше 20 строк, вы получите все строки

, какими бы ни были ваши запросы, поместите их в WITH WITHE AS («ваш запрос здесь»)

и добавьте row_number () over (упорядочить по newid ()) как x в списке выбранных столбцов

WITH CTE AS
  (select *,row_number() over (order by newid()) as x from istasks ) 
  SELECT * 
  FROM CTE 
  CROSS APPLY 
       (SELECT MAX(c2.X) MX, ROUND(.1* MAX(c2.X),0) P  --P is no rows needed according to 10% rule  
        FROM CTE C2
       ) DQ
  WHERE CTE.X <= CASE WHEN P < 20 THEN 20 ELSE P END  --take 20 rows if P < 20
...