查询中的多个联接

Posted

技术标签:

【中文标题】查询中的多个联接【英文标题】:Multiple joins in a query 【发布时间】:2012-01-27 04:21:24 【问题描述】:

我有这个 SP 涉及超过 10 个表。在带下划线的行中,有一个表 AllData,由于 where 子句中的字段名,该表被连接了 3 次。

任何关于如何更好地处理这个复杂查询的建议将不胜感激。大多数情况下,为了避免我多次加入 AllData(别名为 ad1、adl2、adl3)。这可能会影响性能。

这里是sp

ALTER PROCEDURE [dbo].[StoredProc1]
AS
select  case when pd.Show_Photo = '1,1,1'
             then i.id
             else null
        end as thumbimage,
        t1.FPId,
        'WebProfile' as profiletype,
        mmbp.Name as Name,
        t1.Age,
        t1.Height,
        adl.ListValue as AlldataValue1,
        adl2.ListValue as AlldataValue2,
        adl3.ListValue as AlldataValue3,
        c.CName,
        ed.ELevel,
        ed.EDeg,
        NEWID()
from Table2  mmbp, Table3  u
join Table1 t1 on t1.Pid = u.Pid
left join Table4 mmb on t1.Pid= mmb.Pid 
join table5 i on t1.Pid = i.Pid 
join table6 pd on t1.Pid = pd.Pid
join table7 ed on t1.Pid = ed.Pid
join table8 c on t1.xxx= c.xxx
join AllData  adl on t1.xxx = adl.ListKey 
join AllData adl2 on b.ms = adl2.ListKey
join AllData adl3 on b.Diet = adl3.ListKey
where adl.FieldName=xxx and
      adl2.FieldName='ms' and
      adl3.FieldName='Diet' and 
      ------ 

【问题讨论】:

Table2(别名 mmbp)与where 子句中省略条件中的任何其他表之间是否存在连接条件?另外,您能否在运行查询时包含查询的其余部分以及查询计划? 【参考方案1】:

我注意到您似乎在 Table2 和 Table3 之间有一个笛卡尔连接 - 除非其中一个表非常小,否则这可能会极大地影响性能。我建议将 Table2 显式连接到查询中的其他表之一,以提高性能。

【讨论】:

【参考方案2】:

您可以尝试的一件事是将 where 条件移动到连接中

join AllData ad1 on t1.xxx = ad1.ListKey AND ad1.FieldName = xxx
join AllData ad2 on b.ms = adl2.ListKey AND ad2.FieldName = 'ms'
join AllData ad3 on b.Diet = adl3.ListKey AND ad3.FieldName = 'Diet'

这将提供更好的性能,因为连接大小将仅限于您想要的记录。要做到这一点,您可以join AllData ad on (t1.xxx = ad.ListKey AND ad.FieldName = xxx) OR (b.ms = ad.ListKey AND ad.FieldName = 'ms')...。此选项的问题是您不再有 ad1、ad2 等不同的列。

【讨论】:

'这将提供更好的性能,因为连接大小将仅限于您想要的记录' - 将谓词从 where 子句移动到 join 子句不会影响生成的执行计划(inner join in这种情况) - 自己尝试一下 @JCooper:“不太可能影响生成的执行计划”比“不会影响生成的执行计划”更好——除非你自己编写了 SQLServer 优化器,并且知道它在每一种可能的情况下会做什么吗? (鉴于 OP 没有包含整个查询...) @Mark Ba​​nnister - 实际上我没有编写优化器。关键是从逻辑上讲,它们是相同的查询。在内部连接的情况下,连接条件是在连接谓词中还是在 where 子句中指定并且在逻辑上相同都没有关系。左连接是唯一重要的指定连接条件的地方。话虽如此,它们在逻辑上是完全相同的东西,我想说优化器不太可能生成两个不同的计划。 @Mark Ba​​nnister - 只是好奇,您指出“OP 没有包含整个查询”。您是否知道会导致优化器生成不同计划的场景?我想不出, @JCooper:从逻辑上讲,你是对的,但我知道优化器会以意想不到的方式运行。

以上是关于查询中的多个联接的主要内容,如果未能解决你的问题,请参考以下文章

有啥方法可以避免一个查询中的多个联接

使用内部联接更新多个表中的列

sql SQLite不支持更新查询中的联接,这使得在基于多个选项卡中的信息进行更新时出现一些复杂性

在单个查询中使用多个联接

联接 (SQL Server)

使用联接表中的值跨多个表联接