在同一个表上连接多次以获得不同的条件,而不是在聚合表上连接一次

时间:2015-08-13 15:11:47

标签: sql sql-server join optimization sql-server-2008-r2

我目前有一个视图,它在同一条件上多次连接一个表,如:

Select
m.ID,
a.value as value1,
b.value as value2,
c.value as value3,
d.value as value4

from
main_table m
left join other_table a on m.ID = a.ID and a.X = 'this'
left join other_table b on m.ID = b.ID and b.X = 'that'
left join other table c on m.ID = c.ID and c.X = 'third'
left join other table d on m.ID = d.ID and d.X = 'other'

我想知道将四个表组合在一起并将它们聚合起来是否效率更高或更低,以便我可以在一个连接中完成所有这些:

Select
m.ID,
value1,
value2,
value3,
value4

from
main_table m
left join (select ID,
           MAX(case X when 'this' then value end) value1,
           MAX(case X when 'that' then value end) value2,
           MAX(case X when 'third' then value end) value3,
           MAX(case X when 'other' then value end) value4
           from ( 
           select ID,X,value from other_table
           where X = 'this'
           union all
           select ID,X,value from other_table
           where X = 'that'
           union all
           select ID,X,value from other_table
           where X = 'third'
           union all
           select ID,X,value from other_table
           where X = 'other')
           GROUP BY ID) AS A
on A.ID = m.ID

我在试验之前会问,因为实际上,视图比这复杂得多,并且需要很长时间才能重写,所以我想确保我不浪费时间。

基本上,我的问题是执行聚合和group by的成本是否会超过执行这些多个联接的成本。此外,我认为包含这个视图包含许多其他连接(15-20)的事实是相关的,所以我试图通过以任何方式减少该数量进行优化。

编辑此外,我觉得添加涉及链接服务器并且这两个表位于不同数据库上是相关的。我试图减少连接数的另一个原因。

任何见解或帮助都将受到赞赏。

提前致谢。

2 个答案:

答案 0 :(得分:3)

与大多数性能问题一样,您需要在系统上测试数据的不同版本。但是,我认为您想要的聚合查询是:

Select m.ID, value1, value2, value3, value4
from main_table m left join
     (select ID,
             MAX(case X when 'this' then value end) value1,
             MAX(case X when 'that' then value end) value2,
             MAX(case X when 'third' then value end) value3,
             MAX(case X when 'other' then value end) value4
      from other_table
      group by ID
     ) A
     on A.ID = m.ID;

聚合的优点是添加更多值并不会改变性能。添加新连接可能会影响性能,因此在某些时候,聚合可能会优于连接。

答案 1 :(得分:1)

根据我的经验,我在特定的架构设计中遇到了类似的问题,我们将自定义属性及其值存储在实体的单独表中,以及何时我们必须查询实体实例的所有自定义属性数据我们不得不多次加入同桌。

我们已经有效地使用PIVOT语法来绕过多个连接。在你的情况下,这将是。

Select
m.ID,
[this],[that],[third],[other]
from
main_table m
left join
    (
        select id,[this],[that],[third],[other]
            (select id, X from other_table )s
                PIVOT
            ( 
                max(value) 
                    for X in ([this],[that],[third],[other])
            )p 
    )t
on t.id=m.id

N.B:请注意,通过避免所有这些JOINS

,这在我们的案例中带来了巨大的性能提升