SQL:左联接与CASE子查询-效率更高

时间:2018-12-05 01:18:28

标签: sql tsql join left-join outer-apply

你们认为哪个更有效(较少负载)?

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

OR

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个)行)?

2 个答案:

答案 0 :(得分:0)

我会使用plotly::plot_ly(marker=list(size=5,color="black"),type='scatter',mode="markers",x=df$x,y=df$y,showlegend=F) %>% plotly::layout(xaxis=list(title="x",zeroline=F,showticklabels=F,showgrid=F,showgrid=F),yaxis=list(title="y",zeroline=F,showticklabels=F,showgrid=F,showgrid=F)) %>% plotly::add_segments(x=df$arrow.x.start,xend=df$arrow.x.end,y=df$arrow.y.start,yend=df$arrow.y.end,line=list(color="blue")) ,但是写为:

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.gNULL,则结果是不同的。)

在性能方面,t1.p = 1为优化器提供了比LEFT JOIN表达式更多的查询选项,因此它可能更快。但是,通过正确的索引编制,这三个查询都可能具有良好的性能。

答案 1 :(得分:0)

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

在您的示例中没有令人信服的理由使用apply运算符,尽管它们确实比放置在select子句中的相关子查询更好地进行了优化,但它们仍然是相关子查询。我认为,如果没有令人信服的理由选择“更具异国情调”,那就不要使用它。因此,请勿在此处使用Apply运算符,而应使用更标准的左连接。

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

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