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

Posted

技术标签:

【中文标题】随机 10% 的 SQL 查询,最少 20 行【英文标题】:SQL Query for Random 10% with a minimum of 20 rows 【发布时间】:2019-02-01 16:11:40 【问题描述】:

我的任务是生成一份报告,该报告将随机选择 10% 的唯一 ID,除非 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

【问题讨论】:

你能说得清楚一点吗?你是说你想要一个报告,如果它超过 20 行,它将返回整个数据集的 10%?如果少于 20 只给一切? 我不明白。您希望它选择什么唯一的 id?为什么你有 200 个却只选择 20 个? 我认为只有当 10% 的结果集小于 20 时它们才应该返回 20。所以如果 10% 是 316,它应该返回 316 @GordonLinoff 是的@gordonLinoff,当 10% 的结果小于 20 时,它应该返回 20。感谢您的快速回复。我现在将对其进行测试。 【参考方案1】:

我会生成一个按 new_id 排序的 row_number,然后计算出你可以取多少 (N) 行(行 1......N)必须是随机的。如果你有少于 20 行,你会得到所有行

无论您的查询需要是什么,都将其放在 WITH CTE AS ("你的查询在这里")

并将 row_number() over (order by 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

【讨论】:

【参考方案2】:
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

【讨论】:

虽然此代码可能会回答问题,但提供有关代码为何和/或如何回答问题的额外上下文可提高其长期价值。它还有助于避免您的答案被否决或标记为低质量。见How to Write a Good Answer。【参考方案3】:

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

【讨论】:

【参考方案4】:

如果您的表中有一个UniqueID,其中COUNT(UniqueID) 大于1(每个UniqueID),那么UniqueID 不是唯一,所以查询中的TotalCounttotal_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;

【讨论】:

以上是关于随机 10% 的 SQL 查询,最少 20 行的主要内容,如果未能解决你的问题,请参考以下文章

SQL语句如何实现从数据库表中查询随机数据的记录

PostgreSQL 查询随机执行需要几分钟

sql 一个表里已经 有20行数据 ,然后要从另一个表里随机抽取20条 覆盖掉之前的数据

从ES数据库中随机抽样10%的数据

sql简单查询语句

SQL 查询来自不同区域的选择行