0

你们认为哪一个更高效(负载更少)?

SELECT t1.a, 
(CASE
WHEN t1.p=1 THEN t2.g 
WHEN t1.p=2 THEN t3.g
END) as v

FROM t1
LEFT JOIN t2 ON t1.x=t2.x
LEFT JOIN t3 ON t1.y=t3.y

或者

SELECT 
t1.a, t2.v 

FROM t1    
outer apply (
SELECT v= CASE
WHEN t1.p=1 THEN (SELECT v FROM t2 WHERE t1.x=t2.x)
WHEN t1.p=2 THEN (SELECT v FROM t3 WHERE t1.y=t3.y)
END
) t2

只是想弄清楚sql引擎是如何工作的..

[我想在这个问题中研究什么] 在第一次查询中,这些表t2t3始终被调用,但在第二次查询中,只有在案例匹配时才会调用它们(因此负载较少 = 只检查 2 个表而不是 3 个表)排)?

4

2 回答 2

0

我会选择left join,但写成:

SELECT t1.a, COALESCE(t2.g, t3.g) as v
FROM t1 LEFT JOIN
     t2
     ON t1.x = t2.x AND t1.p = 1 LEFT JOIN
     LEFT JOIN t3
     ON t1.y = t3.y AND t1.p = 2;

此逻辑不一定完全等同于您的逻辑,但我怀疑此查询符合您的意图。(例如,如果t2.gis everNULLt1.p = 1,则结果不一样。)

至于性能,LEFT JOIN它为优化器提供了比CASE表达式更多的查询选项,因此它可能会更快。但是,通过适当的索引,所有三个查询都可能具有良好的性能。

于 2018-12-05T01:19:51.893 回答
0

在每个左连接中放置一个额外的谓词t1.p=,以便这些谓词根据结果的需要变得互斥。这将允许使用coalesce代替 case 表达式(但 case 表达式是可以的,它只是一个选项)。

没有令人信服的理由在您的示例中使用 apply 运算符,尽管它们确实比放置在 select 子句中的相关子查询优化得更好,但它们仍然是相关子查询。在我看来,如果“更具异国情调”的选项没有令人信服的理由,请不要使用它。所以,不要在这里使用应用运算符,使用更标准的左连接。

SELECT
    t1.a
  , COALESCE(t2.g,t3.g) AS v
FROM t1
LEFT JOIN t2 ON t1.x = t2.x AND t1.p = 1
LEFT JOIN t3 ON t1.y = t3.y AND t1.p = 2
;

但是,如果您只需要这些相关子查询中的一个(或规定数量)行,那么您将有一个令人信服的理由使用应用程序,例如

SELECT
    t1.a
  , t2.v
FROM t1
OUTER APPLY (
        SELECT
            CASE
                WHEN t1.p = 1 THEN (
                        SELECT TOP(1) t2.g FROM t2  -- top 
                        WHERE t1.x = t2.x
                        ORDER BY t2.z               -- order
                    )
                WHEN t1.p = 2 THEN (
                        SELECT TOP(1) t3.g FROM t3  -- top
                        WHERE t1.y = t3.y
                        ORDER BY t3.z               -- order
                    )
            END AS v
    ) t2

不管意见如何,使用执行计划是比较查询选项的最佳方法。

于 2018-12-05T02:31:13.033 回答