删除相关子查询

Posted

技术标签:

【中文标题】删除相关子查询【英文标题】:Remove correlated sub-query 【发布时间】:2016-01-06 09:06:54 【问题描述】:

您能帮我优化查询吗?我们正在使用相关的子查询来解决我们的问题。如何提高性能并去除相关子查询。

SELECT CAST((CASE WHEN value = 1
  THEN CASE WHEN (SELECT COUNT(records)
                  FROM ABC
                  WHERE ABC.ID = XYZ.ID) > 0
    THEN 1
       ELSE 0 END
             ELSE CASE WHEN (SELECT COUNT(records)
                             FROM PQR
                             WHERE PQR.ID = XYZ.ID) > 0
               THEN 1
                  ELSE 0 END END) AS AA) AS COLUMN FROM XYZ

【问题讨论】:

您能否提供一些示例输入数据和所需的输出 - 这将有助于了解您要实现的目标。 相关子查询不一定很慢。在某些情况下,它们甚至可能是最快的方法。如 Arth 的回答所示,它是 EXISTS,但您应该使用,而不是 COUNT。为了使这个不相关,您可以改用IN,但如前所述,这并不一定意味着查询变得更快;它甚至可以变得更慢。无论如何,请确保在相关列上有索引。 【参考方案1】:

试试这个。我已将子查询移至单独的临时表。

SELECT XYZ.id, 
        CASE WHEN XYZ.value = 1
             THEN CASE WHEN T.cnt > 0 THEN 1 ELSE 0 END
             ELSE CASE WHEN T2.cnt > 0 THEN 1 ELSE 0 END
             END as column
FROM XYZ
    LEFT JOIN ( SELECT id, COUNT(*) AS cnt FROM ABC 
                GROUP BY id) AS T ON XYZ.id = T.id
    LEFT JOIN ( SELECT id, COUNT(*) AS cnt FROM PQR
                GROUP BY id) AS T2 ON XYZ.id = T2.id
GROUP BY XYZ.id

另一种解决方案。只需检查表 ABC 和 PQR 中的存在 ID。感谢评论员。

SELECT XYZ.id,
       CASE WHEN XYZ.value = 1
            THEN T.id IS NOT NULL
            ELSE T2.id IS NOT NULL
            END AS column
FROM XYZ
   LEFT JOIN (SELECT DISTINCT id FROM ABC) AS T ON XYZ.id = T.id
   LEFT JOIN (SELECT DISTINCT id FROM PQR) AS T2 ON XYZ.id = T2.id

【讨论】:

此查询可能需要更多时间,因为它包含更多 group by 并与发布的 OP 相比加入。 不确定是否需要选择列中的 xyz.id 或外部查询中的 group by 子句。 无需按 ID 分组并计入子查询。你可以简单地select distinct id 然后检查t.id is not nullt2.id is not null。这应该会更快,因为 DBMS 的工作量更少。 你可以去掉内层:CASE WHEN T.id IS NOT NULL THEN 1 ELSE 0 ENDT.id IS NOT NULL..至少在 mysql 中是一样的【参考方案2】:

你应该尽量避免在这里使用COUNT,你不关心每种情况下有多少行,只关心它们是否EXIST

MySQL 中的布尔条件分别为 TRUEFALSE 返回 10,因此您可以节省大量语法。

我认为这就是你想要的,非常简化:

SELECT (x.value  =1 AND EXISTS (SELECT 1 FROM ABC a WHERE a.id = x.id))
         OR 
       (x.value !=1 AND EXISTS (SELECT 1 FROM PQR p WHERE p.id = x.id)) column
  FROM XYZ x

或者可能:

SELECT EXISTS (SELECT 1 FROM ABC a WHERE a.id = x.id) column
  FROM XYZ x
 WHERE x.value = 1
 UNION ALL
SELECT EXISTS (SELECT 1 FROM PQR p WHERE p.id = x.id)
  FROM XYZ x
 WHERE x.value != 1

或者如果你喜欢案例:

   SELECT CASE 
            WHEN x.value = 1 THEN EXISTS (SELECT 1 FROM ABC a WHERE a.id = x.id)
            ELSE EXISTS (SELECT 1 FROM PQR p WHERE p.id = x.id)
          END column
     FROM XYZ x  

【讨论】:

以上是关于删除相关子查询的主要内容,如果未能解决你的问题,请参考以下文章

BigQuery - 联合上的相关子查询不起作用

相关子查询 和 不相关子查询

SQL练习 高级子查询

相关子查询 与非相关子查询

SQL相关子查询与非相关子查询

转载---相关子查询和非相关子查询