回答

收藏

sql避免笛卡尔积

技术问答 技术问答 209 人阅读 | 0 人回复 | 2023-09-14

我对SQL还是很陌生,并且正在为查询而苦苦挣扎(使用Access,FWIW)。我已经搜索并搜索了StackOverflow,但没有看到这种确切的情况。(这也可能是因为我不知道正确的搜索词。)
0 }- q, d0 e0 r4 F) A/ Y! p3 b我有两个非常简单的表,其中包含相似的数据。3 O+ O8 [$ b5 Z
table1: state, lname, fname, network# L9 v$ S& u6 h  s- c1 R
table2: state, lname, fname, network/ L' Q0 \$ l4 ]! B7 R
我想要的是在两个表以及该人所在的每个表的网络中找到匹配的每个人/州组合:- F3 Q7 h6 L1 e5 c) q/ L
state, lname, fname, t1.network, t2.network.5 w* [  z, G3 q( C9 _
此人在每个表中可能位于多个网络中。我想查看此人所属的每个网络(从两个表中)。1 `* s8 ~4 s! C/ T4 v, s
我从使用JOIN开始,如下所示:
' _" @2 |$ C/ }; c8 P, [8 O( sSELECT t1.state, t1.lname, t1.fname, t1.network, t2.network
) _+ U: G! d2 xFROM t1 INNER JOIN t2
) B. G& `' U6 Y) f' G9 JON t1.fname=t2.fname AND t1.lname=t2.lname AND t1.state=t2.state
3 O0 f* v9 F# j  Q4 T1 _8 ~GROUP BY t1.state, t1.lname, t1.fname, t1.network, t2.network
7 x: l" i+ h  W) [: D1 k我很快发现我得到了笛卡尔积。因此,如果“ NY,Smith,John”在t1处于两个网络中,而在t2处于三个网络中,我将得到如下信息:
. T7 _1 Z1 `# ?. ANY, Smith, John, NetworkA, NetworkB
: y7 M+ V" o: m& iNY, Smith, John, NetworkA, NetworkA/ z; ~% X& H, ~/ l4 N) ?8 ]( c
NY, Smith, John, NetworkB, NetworkA8 e8 v6 f3 F* C# p/ {
NY, Smith, John, NetworkB, NetworkB7 m! v, I0 q% n
NY, Smith, John, NetworkA, NetworkC
) k* |( p9 y& T0 hNY, Smith, John, NetworkB, NetworkC  m% u/ P$ I7 g4 Q/ l  b  b0 _
我真正想要看到的只是:8 e' B0 ~; h. w
NY, Smith, John, NetworkA, NetworkA) M% S* G4 o" |# k% o( n1 p. k! m
NY, Smith, John, NetworkB, NetworkB
( Y% S- |3 Q# K! d) Y/ pNY, Smith, John, NULL, NetworkC+ e8 \5 Y. H: q- O/ N4 g
谁能给我一些有关如何进行或向正确方向发展的建议?
" A9 R. k: \7 c9 q# T# f                6 y8 U" d  K$ m
解决方案:
4 a9 _' I$ B0 J  }' j! W8 m                8 c1 n* ~0 `7 C5 b

7 c/ w2 A2 \% p; ]/ _( _7 B
/ z! O0 U2 h9 a2 C                因此,看起来您希望每个表中的所有记录都是相同的,然后只希望每个表中的记录都是不同的。这意味着您需要UNION 3组查询。
) S: _- o& W3 O# \尝试这样的事情:) d. b, A' J' V5 g
SELECT t1.state, + C& o3 T& w/ M; K# a% N+ L5 l
   t1.lname, ( \/ W- R2 Q+ x& N6 |
   t1.fname, . X9 Y8 r6 S! o5 D; C  Q: g
   t1.network as t1Network, 5 m& O4 l% h4 L5 {- ^
   t2.network as t2Network
( U1 l: E5 C7 YFROM table1 t1
4 @. D/ a0 v. W3 E! }   INNER JOIN table2 t2 8 u# v. {; D+ Y7 f: R6 X2 u  ^
      ON t1.fname=t2.fname 9 Y+ v! I+ O+ O) S6 q2 [: s, T
      AND t1.lname=t2.lname % A" s- E" q$ K* o
      AND t1.state=t2.state. R$ F: r/ g0 |
      AND t1.network=t2.network! t$ d  s: @" b/ Z! a& I; d# g
UNION - B3 [$ I0 b3 j* R
SELECT t1.state,
" z$ |: k& w/ h% z9 k4 K+ X   t1.lname, 8 q3 l( s4 _, z  }& {" x
   t1.fname,
/ [$ F8 r4 Z7 `( u   t1.network as t1Network, - c: x+ [7 [  X7 x* X
   t2.network as t2Network, Z$ ^. S  j" C6 C+ ]
FROM table1 t1 . M1 r# [3 q4 ^3 D/ u8 ]
   LEFT JOIN table2 t2
1 q  }. [6 R0 u: o- h& I* F      ON t1.fname=t2.fname 5 G& R; h3 X8 Q
      AND t1.lname=t2.lname
+ Z) ?2 O& H& k/ k7 K: D( G- K      AND t1.state=t2.state1 h) M3 z0 g( C6 R% a# }+ J
      AND t1.network=t2.network
) {+ j& A2 j6 d/ mWHERE t2.network IS NULL
  ]+ C5 E! \& E! @+ lUNION & F; _$ j2 e9 X  t9 v
SELECT t2.state, % Y; Q4 `; O. l8 _, b9 o
   t2.lname, # n8 |8 L6 d8 t& }# I% j
   t2.fname,
4 y8 T* |* k* n% k  P( Y& t   t1.network as t1Network, 0 z/ F8 e: ?4 {" k
   t2.network as t2Network
5 O: F7 v2 P/ x0 h6 J% ~FROM table2 t2
0 o! K, Q* [# i4 n$ A   LEFT JOIN table1 t1
3 J: t+ Q) {0 w% G4 k" c      ON t1.fname=t2.fname
+ e6 K5 r4 l; e, \! D; ^( O      AND t1.lname=t2.lname
/ o1 v; [* E0 L      AND t1.state=t2.state
2 C8 |" s! V% z- g+ J      AND t1.network=t2.network; Z: t' z1 w3 l2 Z* M, f9 @3 Y0 j
WHERE t1.network IS NULL! ?- f5 {5 d4 x; I$ Q
这应该给您您想要的结果。5 b7 `# }' L7 ~2 q+ S' f
这是要确认的SQL Fiddle。
+ _* [" f7 S2 m/ F1 G+ L- 编辑' T* q) ]7 `/ K: m
今天不考虑-您实际上不需要第一个查询。您可以从第二个查询中删除WHERE条件,其工作方式相同。疲劳的 :-)
, l3 h4 u' q! n5 Q% d0 U这是更新后的查询-两者都应该正常工作,这更容易阅读:# X0 `9 S$ X' c/ b+ P" P6 J/ I
SELECT t1.state,
$ Q7 I# v2 U! i6 u$ R& z   t1.lname, , u' t' z+ w% a8 P" k0 o* z
   t1.fname,
$ J& a* V9 F4 u  K1 _   t1.network as t1Network,
! V- s) v8 v4 j/ F3 I( R* N, f& w   t2.network as t2Network
* Q2 e! b0 ~" ]/ L, VFROM table1 t1
3 H# F, A5 q5 j6 W, V# q   LEFT JOIN table2 t2 $ Y2 A- h  O: n" B* {2 x" ~
      ON t1.fname=t2.fname 6 N0 K8 b- s8 D* I' D, A( j
      AND t1.lname=t2.lname 9 o! O, Q  ^3 q1 v
      AND t1.state=t2.state! H5 T) x) {# i* C7 C3 u
      AND t1.network=t2.network) h* W2 z, t! \2 W( `6 y$ p( ^' z' s
UNION . E* c& A# w8 f
SELECT t2.state, + `: ?9 {9 g7 s4 O/ t0 G% J; w
   t2.lname,
! K8 E, e, @, [+ t! B- R8 ^   t2.fname,
* h+ ?/ Q, \' D  S! b, ^7 T   t1.network as t1Network, % F4 O4 |! r+ J* z5 @, s
   t2.network as t2Network  S9 o' c& C+ h6 U
FROM table2 t2 8 q0 C9 z5 [6 U  [6 D6 h
   LEFT JOIN table1 t1% A6 N1 s! h% m* E8 L
      ON t1.fname=t2.fname
, i/ a1 ?5 V) P4 [      AND t1.lname=t2.lname : {. L- c4 w3 B0 X) w% V! \+ ~4 h
      AND t1.state=t2.state
0 b7 b) i: e/ X% g# I2 N( t      AND t1.network=t2.network
' F+ j# \$ T. `. ^" jWHERE t1.network IS NULL
2 C1 ]" u& u) F8 y2 B' j1 a1 f/ ~5 P和更新的小提琴。
: J  E4 L% c% V1 f8 X) C, y6 `) e5 e顺便说一句-它们都应该在MSAccess中都支持UNION。% W5 N( n$ v3 h5 F; l$ @
祝你好运。
分享到:
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则