随机 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 不是唯一,所以查询中的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;
【讨论】:
以上是关于随机 10% 的 SQL 查询,最少 20 行的主要内容,如果未能解决你的问题,请参考以下文章