如何优化涉及内部连接的条件子选择?
Posted
技术标签:
【中文标题】如何优化涉及内部连接的条件子选择?【英文标题】:How to optimize conditional sub-selects that involve inner joins? 【发布时间】:2013-03-14 10:50:24 【问题描述】:我有一个 SQL 查询 (MS SQL 2008),我想在速度方面进行优化。它具有以下结构(实际上只有在 case 语句中有 10 种不同的 when-case)。
重要的位是 case 语句中的子选择,它涉及附加表之间的内部连接以及对 FROM 子句中的一个表 (table1) 的引用。
我在想我可以在 FROM 子句中使用左(外)连接而不是子选择来优化它,但我不确定,因为子选择也涉及内连接。然后我会在 FROM 子句中使用两个左连接,现在我在子选择中使用内部连接吗?从第二个 when-case 开始,AnotherTable3 将如何工作?
非常感谢任何想法。
SELECT table1.a,
table2.b,
CASE
WHEN table1.XY = 1 THEN
(SELECT something
FROM AnotherTable1 at1
INNER JOIN AnotherTable2 at2
ON at1.x = at2.y
WHERE at1.abc = table2.abc)
WHEN table1.XY = 2 THEN
(SELECT something
FROM AnotherTable1 at1
INNER JOIN AnotherTable3 at3
ON at1.x = at3.y
WHERE at1.abc = table2.abc)
END AS [problem]
FROM MyTable1 table1
INNER JOIN MyTable2 table2
ON table1.a = table2.b
【问题讨论】:
在这种情况下我通常写select ... from MayTable1 table1 ... left join (select ... from AnotherTable1 at1 ...) at1 on at1.abc = table2.abc and table1.XY = 1 ...
比较this question and its answers
【参考方案1】:
在这种特殊情况下,当具有相同条件的部分只需要三个左连接时,AnotherTable1 会同时连接:
SELECT table1.a,
table2.b,
CASE
WHEN table1.XY = 1 THEN
?.something -- from whereever it's coming
WHEN table1.XY = 2 THEN
?.something -- from whereever it's coming
END AS [problem]
FROM MyTable1 table1
INNER JOIN MyTable2 table2
ON table1.a = table2.b
LEFT JOIN AnotherTable1 at1
ON at1.abc = table2.abc
LEFT JOIN AnotherTable2 at2
ON at1.x = at2.y
LEFT JOIN AnotherTable3 at3
ON at1.x = at3.y
在更一般的情况下,你会有这个选项
FROM MyTable1 table1
INNER JOIN MyTable2 table2
ON table1.a = table2.b
LEFT JOIN
(select *
from AnotherTable1 at1
INNER JOIN
AnotherTable2 at2
ON at1.x = at2.y
) at1
ON at1.abc = table2.abc
...
【讨论】:
【参考方案2】:您可以尝试以下操作:
SELECT
table1.a,
table2.b,
CASE
WHEN table1.XY = 1 THEN at2.something
WHEN table1.XY = 2 THEN at3.something
END
FROM MyTable1 table1
INNER JOIN MyTable2 table2
ON table1.a = table2.b
LEFT JOIN AnotherTable1 at1
ON at1.abc = table2.abc
INNER JOIN AnotherTable2 at2
ON at1.x = at2.y
INNER JOIN AnotherTable3 at3
ON at1.x = at3.y
但检查结果,还要记住 at2 和 at3 列必须具有相同的数据类型
【讨论】:
这似乎是错误的:当 at1 和 table2 之间的左连接将 at1 评估为 null 时,at1 和 at2 之间的内连接失败并且行丢失。这与原始查询不同 行也会在原始查询中丢失,我不知道数据库模式,所以猜测有外键或其他东西,因为@DotNetDeveloper 这样做是这样的 这样我得到的结果更少,问题正如迈克尔上面所说的那样。我认为问题在于 INNER JOIN AnotherTable2 at2 不仅意味着对前一个左连接的内连接,而且是对所有数据的内连接。以上是关于如何优化涉及内部连接的条件子选择?的主要内容,如果未能解决你的问题,请参考以下文章