我在存储过程中编写了一些SQL,以将数据集减少为我想要报告的有限随机行数。
报告以Group
Users
开头,并应用过滤器来指定所需的随机行总数(@SampleLimit
)。
为了达到预期的效果,我首先创建一个CTE(临时表):
top(@SampleLimit)
已应用group by UserId
(因为UserID多次出现)order by NEWID()
将结果按随机顺序排列SQL:
; with cte_temp as
(select top(@SampleLimit) UserId from QueryResults
where (GroupId = @GroupId)
group by UserId order by NEWID())
我有了这个结果集,然后删除UserId在上一步中创建的CTE NOT IN
的任何结果。
delete QueryResults
where (GroupId = @GroupId) and (UserId not in(select UserId from cte_temp))
我遇到的问题是,我不时会得到比@SampleLimit
中指定的结果更多的结果,有时候它的效果与预期完全相同。
我已经尝试分解SQL并在应用程序之外执行它,但我无法重现该问题。
我正在做的事情有什么根本性的错误可以解释为什么我偶尔会得到更多我要求的结果?
为了完整性 - 我的重新考虑的解决方案基于以下答案:
select top(@SampleLimit) UserId into #T1
from QueryResults
where (GroupId = @GroupId)
group by UserId
order by NEWID()
delete QueryResults
where (GroupId = @GroupId) and (UserId not in(select UserId from #T1))
答案 0 :(得分:5)
涉及SELECT
的{{1}}语句执行的次数是不确定的。
如果在NEWID()
和QueryResults
之间获得嵌套循环反半连接,并且计划中没有假脱机,则可能会重新评估{{1}中的行数次这意味着对于每个外行,与cte_temp
进行比较的集合可能完全不同。
您可以将结果具体化为临时表,而不是使用CTE来避免这种情况。
QueryResults
然后在NOT IN