回答

收藏

奇怪的INNER JOIN语法和封装

技术问答 技术问答 80 人阅读 | 0 人回复 | 2023-09-13

我通常对JOINS十分熟悉,但这是新的。; u/ t8 r! y; p4 N5 E
假设三个表(两个表的典型情况和第三个链接器表):$ j' x- d- G5 ~4 _- d% O! U9 T
Customer  Product  Transaction
, F: C% z8 l; v+ x+ o& I  P--------  -------  -----------
1 a5 }$ K+ R; M( t6 QID        ID       CustomerID
3 ~& S- `+ x2 n1 U; e8 n7 N6 B5 O* ~Name      Desc     ProductID. S. ^& R4 ~3 T+ A6 D$ G
          Cost     Date5 n0 {( c2 d; Y+ q& o

1 ^4 w* @" e  `% R, W1 [) Y(出于简化目的,我无法复制实际的结构,这不是我的代码。)+ U5 ]+ C$ e% Q& ^
通常,要获得“谁在什么时候买了什么”的表格,我可以这样做:
' S8 x. Y2 V7 `' {/ DSELECT Customer.Name, Product.Desc, Transaction.Date
2 c7 {: n7 h% {FROM Product" t# f# b  a2 x/ i
INNER JOIN Transaction ON Transaction.ProductID = Product.ID
( Y$ t4 ^* o0 Z9 i: V7 \8 T+ g( YINNER JOIN Customer ON Transaction.CustomerID = Customer.ID
4 n- n8 o  P7 F, C但是我已经看到了这个:5 u4 U, L9 g# w/ m: Y+ {2 ]
SELECT Customer.Name, Product.Desc, Transaction.Date7 Q1 J7 K$ e" X' h9 I
FROM Product9 ^! C9 F4 V0 @# A8 s& _0 m, u
INNER JOIN ( Transaction; k$ O9 T/ {" ?" H5 I+ x7 H. V
      INNER JOIN Customer ON Transaction.CustomerID = Customer.ID)- l" V4 Y- i+ E  Y
ON Transaction.ProductID = Product.ID
8 [- r8 E5 G; n+ T  z这是什么?只是另一种语法,还是一种性能技巧?$ r+ e% t- V# v/ P7 @3 k, \3 Q" J
(它在SQLServer,FYI上,但是大概可以应用于其他…)
* ?9 U, @2 h2 {  q/ e- c/ A( \& C                6 K* s# T& _. x8 c# k0 g' q
解决方案:7 n: \0 ?$ s) o& ~( t2 f1 F
               
" W* g0 p/ M  _% o7 u9 a2 Q; j& {8 F3 S/ s1 }+ X% F

5 T2 _' V) v/ c+ @                括号不会改变语义。ON子句的位置控制联接的逻辑处理顺序。, u1 Z: [4 ~! O+ p
第一次查询; X- Z6 M7 ?$ ~, ^: W* m
SELECT Customer.Name,
2 K4 g+ [; [: F0 S+ T7 c# v5 h       Product.Desc,: }- D5 \! z! N" ~* b+ x- d- Z
       Transaction.Date9 K% M  V6 ~/ S: z
FROM   Product7 J  P% t3 K- Q0 G* s7 v0 w
       INNER JOIN Transaction5 S0 ?& N! V( U
         ON Transaction.ProductID = Product.ID
' T7 i9 a# f0 W; f8 B5 n       INNER JOIN Customer
' v- V# b* x9 |         ON Transaction.CustomerID = Customer.ID& q$ R2 V8 b& T2 c; l6 _6 N- z
第二查询7 V: Q% E3 i: f
(多余的括号已删除)
8 L8 T4 |( H# o# x; b' @, T: z9 aSELECT Customer.Name,7 M0 i' I( I  c
       Product.Desc,$ M% u6 W1 ]6 x& o
       Transaction.Date+ x" Z: Q2 x& x- h
FROM   Product+ T$ n2 x5 {# D/ G! k
       INNER JOIN Transaction
) x2 D* P, K3 P1 v                  INNER JOIN Customer
2 R  m+ D, n% D                    ON Transaction.CustomerID = Customer.ID
9 A1 i  V& l6 _  T% j8 ]6 h         ON Transaction.ProductID = Product.ID
0 w; T5 \" i4 c6 r2 w" O因此, 从逻辑上讲, 在您的第一个示例中,连接Transaction,. o+ g1 t6 P6 d
Product首先发生,然后将由此产生的虚拟表连接到Customer,而在您的第二个示例中,Transaction,$ n" e# A" D; q/ G+ [5 v3 Q
Customer首先发生连接,然后将由此产生的虚拟表连接到Product  q& i" o/ @" e- B- F, ]
这仅是逻辑上的,并且由于内部联接既具有关联性又具有可交换性,因此这对执行计划可能没有任何影响(除非您添加OPTION (FORCE
+ i) k1 j- m: C+ X( d7 TORDER)到查询中),但对于外部联接则可以。
分享到:
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则