删除相关子查询
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 null
和t2.id is not null
。这应该会更快,因为 DBMS 的工作量更少。
你可以去掉内层:CASE WHEN T.id IS NOT NULL THEN 1 ELSE 0 END
和T.id IS NOT NULL
..至少在 mysql 中是一样的【参考方案2】:
你应该尽量避免在这里使用COUNT
,你不关心每种情况下有多少行,只关心它们是否EXIST
。
MySQL 中的布尔条件分别为 TRUE
和 FALSE
返回 1
或 0
,因此您可以节省大量语法。
我认为这就是你想要的,非常简化:
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
【讨论】:
以上是关于删除相关子查询的主要内容,如果未能解决你的问题,请参考以下文章