SQL连接格式 - 嵌套的内连接

时间:2011-02-24 01:33:23

标签: sql sql-server sql-server-2005 tsql

我在遗留系统中有以下SQL语句,我正在重构。对于这个问题,它是一个简略的视图,暂时只返回count(*)。

SELECT COUNT(*)
FROM Table1 
    INNER JOIN Table2 
        INNER JOIN Table3 ON Table2.Key = Table3.Key AND Table2.Key2 = Table3.Key2 
    ON Table1.DifferentKey = Table3.DifferentKey

它生成了大量的记录并杀死了系统,但有人可以解释一下语法吗?这可以用其他任何方式表达吗?

  • 表1包含419行
  • 表2包含3374行
  • 表3包含28182行

编辑:

建议重新格式化

SELECT COUNT(*)
FROM Table1 
    INNER JOIN Table3
          ON Table1.DifferentKey = Table3.DifferentKey
    INNER JOIN Table2 
          ON Table2.Key = Table3.Key AND Table2.Key2 = Table3.Key2

2 个答案:

答案 0 :(得分:18)

为了便于阅读,我重新构建了查询...从表观最高级别为Table1开始,然后与Table3绑定,然后table3与table2绑定。如果你遵循关系链,就会更容易理解。

现在,回答你的问题。作为笛卡儿积的结果,你得到了很大的数量。对于Table1中与Table3匹配的每条记录,您将拥有X * Y.然后,对于table3和Table2之间的每个匹配将产生相同的影响... Y * Z ...因此,您在表1中只有一个可能的ID的结果可以有X * Y * Z记录。

这是基于不知道表格的规范化或内容如何...如果密钥是PRIMARY密钥而不是..

Ex:
Table 1       
DiffKey    Other Val
1          X
1          Y
1          Z

Table 3
DiffKey   Key    Key2  Tbl3 Other
1         2      6     V
1         2      6     X
1         2      6     Y
1         2      6     Z

Table 2
Key    Key2   Other Val
2      6      a
2      6      b
2      6      c
2      6      d
2      6      e

因此,表1加入表3将导致(在此场景中)有12条记录(每条记录在1中加入,每条记录在3中)。然后,表2中每个匹配记录的所有次数(5条记录)...将返回总计60(3 tbl1 * 4 tbl3 * 5 tbl2)计数。

所以,现在,根据你的1000条记录进行扩展,你会看到一个混乱的结构如何扼杀一头牛(可以这么说)并杀死性能。

SELECT
      COUNT(*)
   FROM
      Table1 
         INNER JOIN Table3
            ON Table1.DifferentKey = Table3.DifferentKey
            INNER JOIN Table2
               ON Table3.Key =Table2.Key
               AND Table3.Key2 = Table2.Key2 

答案 1 :(得分:13)

由于您已经收到有关查询的帮助,我会捅你的语法问题:

第一个查询使用一些鲜为人知的ANSI SQL语法,允许您在joinon子句之间嵌套连接。这允许你对连接进行范围/分层,并且可能会打开许多​​其他邪恶的,神秘的东西。

现在,虽然嵌套连接不能在连接层次结构中引用比其直接父级更高的连接,但是在它之上或在其分支之外的连接可以引用它...这正是这个丑陋的小家伙正在做:

select
 count(*)
from Table1 as t1
join Table2 as t2
    join Table3 as t3
    on t2.Key = t3.Key                   -- join #1
    and t2.Key2 = t3.Key2 
on t1.DifferentKey = t3.DifferentKey     -- join #2  

这看起来有点令人困惑,因为连接#2将t1连接到t2而没有专门引用t2 ...但是,它通过t3间接引用t2,而t3连接到连接#1中的t2。虽然这可能有用,但您可能会发现以下内容更多(视觉上)线性且吸引人:

select
 count(*)
from Table1 as t1
    join Table3 as t3
        join Table2 as t2
        on t2.Key = t3.Key                   -- join #1
        and t2.Key2 = t3.Key2   
    on t1.DifferentKey = t3.DifferentKey     -- join #2

就我个人而言,我发现以这种方式嵌套可以通过概述关系层次结构的每一层来保持我的陈述整洁。作为旁注,您不需要指定 inner join 隐式内部,除非另有明确标记。

相关问题