【问题标题】:Query Hangs when NOT IN is used with a SUBQUERY which returns NULL当 NOT IN 与返回 NULL 的 SUBQUERY 一起使用时,查询挂起
【发布时间】:2016-01-25 15:18:45
【问题描述】:

我们正在这样做:

SELECT x from d where x not in
(
SELECT xx FROM a
INNER JOIN aa ON a.col = aa.col

UNION
SELECT xx FROM b 
INNER JOIN bb on a.col = bb.col
)

当我们单独运行子查询时,它在10秒内执行并返回0条记录,因为INNER JOIN中使用的表之一是空白的

但是,当我们运行整个查询时,它会持续运行超过 2 个小时,并且永远不会结束。

当整个查询运行时,我们希望看到来自 d 的所有数据,但是为什么查询会挂起?

【问题讨论】:

  • 执行计划是什么?
  • NOT IN 子查询永远不应该返回 NULL,将 WHERE xx IS NOT NULL 添加到两个选择中。
  • 尝试使用 NOT EXISTS
  • 可能是错字,但派生表中的最后一个查询将a.col = bb.col 作为连接条件,应该是b.col = bb.col。此外,最好在该查询中使用 UNION ALL(除了任何其他优化)。

标签: sql sql-server


【解决方案1】:

听起来子查询正在为 d 中的每个 x 运行。尝试将其作为 CTE,如果临时表失败,则预先计算子查询,然后才使用它从 x 中排除记录。

--CTE:
WITH subq AS
(
SELECT xx FROM a
INNER JOIN aa ON a.col = aa.col

UNION
SELECT xx FROM b 
INNER JOIN bb on a.col = bb.col
)
SELECT x from d left join subq on subq.xx = d.x where subq.xx is null

临时表方法完全相同,只需为 col xx 创建一个包含一行的临时表(我不确定您的数据类型是什么)并用子查询填充它。

【讨论】:

  • 您好,您的建议有效,但我想知道查询挂起的原因?
  • 其他人评论了子查询中的空值 - 这可能是导致挂起的原因。我最初的想法是,这是一个 10 秒的子查询,这是巨大的。如果执行不止一次,或者我怀疑 d 中的每个 x,那么整个查询将花费大量时间来运行,并且似乎已经挂起。
【解决方案2】:

试试这个

SELECT x from d where x not in
(select isnull(xx,'-9999999') from
(
SELECT xx FROM a
INNER JOIN aa ON a.col = aa.col

UNION
SELECT xx FROM b 
INNER JOIN bb on a.col = bb.col
)
)

【讨论】:

    【解决方案3】:

    试试这个

    select x from d 
        where not exists(Select top 1 1 from a inner join aa on a.col = aa.col where d.x = xx)
        and not exists (Select top 1 1 from b inner join bb on a.col = bb.col where d.x = xx)            
    

    【讨论】:

      猜你喜欢
      • 2013-09-18
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-05-12
      • 1970-01-01
      • 2016-10-24
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多