SQL查询随机10%,最少20行

时间:2019-02-01 16:11:41

标签: sql sql-server reporting-services sql-server-2008-r2 ssrs-2008

我的任务是生成一个报告,该报告将随机选择一个唯一ID的10%,除非10%少于20个项目,在这种情况下,报告将选择20个随机ID。 我一直在使用NewID来生成10%,但这并不是最好的,因为它给了我可变的结果(即:大于或小于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 :(得分:1)

我将生成一个按new_id排序的row_number,然后计算出可以随机抽取的行数(N行)是1行。如果少于20行,则得到所有行

无论您需要查询什么内容,都将其放在 使用CTE AS(“您的查询在这里”)

并将row_number()(按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

答案 1 :(得分:1)

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

答案 2 :(得分:0)

如果您不需要知道总行数,那么下面的构造可能是满足“ 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

答案 3 :(得分:0)

如果您的表中有一个UniqueID大于1(每个COUNT(UniqueID))的UniqueID,则该 UniqueID 不是唯一 ,因此查询中的TotalCounttotal_count列应返回相同的值。

要过滤掉记录的前10%(或至少20条),可以计算一个随机行号(使用NEWID()),然后对其应用过滤器(包括记录总数)。行数和记录总数都可以使用 window函数(带有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;