【发布时间】:2020-06-21 06:11:55
【问题描述】:
我正在尝试编写一个查询,从两个表中提取多个列,然后查看在过去 28 天内是否有另一个实例包含相同类型的数据。
我的查询工作正常,它看起来像这样:
SELECT
a.col_a
,a.col_b
,a.col_c
,b.col_a
,b.col_b
,CASE WHEN EXSISTS (SELECT a_sub.col_a
FROM a_sub
INNER JOIN b_sub
ON a_sub.x = b_sub.x
WHERE
b.col_a = b_sub.col_a
AND b.col_b <> b_sub.col_b
AND a.date > a_sub.date
AND a.date <= DATEADD(d, 28, a_sub.date)
AND a.col_c = a_sub.col_c
AND (a.col_d IS NULL OR a.col_d <> 7)
AND (a_sub.col_d IS NULL OR a_sub.col_d <> 7)
) THEN 'Yes'
ELSE 'No'
END AS IsRepeat28
FROM a
INNER JOIN b ON a.x = b.x
这不是特别快,但也不会太慢而不会成为问题。问题是我需要重复上述 WHEN EXISTS 子查询,但要在 21、14、7 和 1 天期间重复 5 次 - 然后查询时间从大约 15 秒到大约 10 分钟。
我还需要调整日期以及标记“IsRepeat”的行,还有一个基于“HasRepeat”的版本
AND a_sub.date > a.date AND a_sub.date <= DATEADD(d, 28, a.date)
代替原来的
AND a.date > a_sub.date AND a.date <= DATEADD(d, 28, a_sub.date)
这意味着有 10 个这些 EXISTS 子查询,这需要将近 45 分钟。
我的问题确实是双重的;有没有更有效的方法来编写这个子查询,有没有更好的方法来重复它而不是将几乎相同的代码写出 10 次?
【问题讨论】:
-
如果不是检查窗口中是否存在日期,而是检索前一个匹配日期,则可以使用一个日期为每个持续时间构建标志。这应该让你减少一次往返。如果您使用的是现代版本的 SQL Server,那么您可以使用 LAG 窗口函数将其归结为对表的单次读取。
-
更改参数,查询需要更长的时间来执行。这让我想起了我在创建和重用低效执行计划时遇到的问题。我建议您可以尝试将 OPTION(RECOMPILE) 命令添加到您的代码中,也许它会有所帮助:stackoverflow.com/questions/20864934/… - 但请注意,我是 SE 上的一个随机陌生人,我建议您一些我自己甚至不完全理解的东西,所以请好好研究一下 :)
-
性能问题的起点通常是实际的执行计划。请参阅paste the plan,了解在您的问题中包含执行计划的方法。存在哪些索引(如果有)?
标签: sql-server tsql subquery exists