Tia*_*ong 23 sql join outer-join
很容易理解为什么左外连接不是可交换的,但是我在理解它们是否是关联时遇到了一些麻烦.一些在线消息来源表示他们不是,但我没有设法说服自己这是事实.
假设我们有三个表:A,B和C.
设A包含两列,ID和B_ID,其中ID是表A的主键,B_ID是对应于表B的主键的外键.
设B包含两列,ID和C_ID,其中ID是表B的主键,C_ID是对应于表C的主键的外键.
设C包含两列,ID和VALUE,其中ID是表C的主键,VALUE只包含一些任意值.
那不(A left outer join B) left outer join C
应该等于A left outer join (B left outer join C)
?
Prz*_*lej 23
在这个帖子中,据说它们不是关联的:LEFT OUTER JOIN是关联的吗?
但是,我在网上找到了一些书,其中OUTER JOIN是关联的,当最左侧和最右侧的表没有共同的属性时(这里).
这是一个图形演示文稿(MSPaint ftw):
另一种看待它的方式:
既然你说表A加入B,而B加入C,那么:
我没有看到任何可能的情况,在您描述的条件下,根据LEFT连接的顺序会有数据丢失.
基于Tilak在他的答案(现已删除)中提供的数据,我构建了一个简单的测试用例:
CREATE TABLE atab (id NUMBER, val VARCHAR2(10));
CREATE TABLE btab (id NUMBER, val VARCHAR2(10));
CREATE TABLE ctab (id NUMBER, val VARCHAR2(10));
INSERT INTO atab VALUES (1, 'A1');
INSERT INTO atab VALUES (2, 'A2');
INSERT INTO atab VALUES (3, 'A3');
INSERT INTO btab VALUES (1, 'B1');
INSERT INTO btab VALUES (2, 'B2');
INSERT INTO btab VALUES (4, 'B4');
INSERT INTO ctab VALUES (1, 'C1');
INSERT INTO ctab VALUES (3, 'C3');
INSERT INTO ctab VALUES (5, 'C5');
SELECT ab.aid, ab.aval, ab.bval, c.val AS cval
FROM (
SELECT a.id AS aid, a.val AS aval, b.id AS bid, b.val AS bval
FROM atab a LEFT OUTER JOIN btab b ON (a.id = b.id)
) ab
LEFT OUTER JOIN ctab c ON (ab.bid = c.id)
ORDER BY ab.aid
;
Run Code Online (Sandbox Code Playgroud)
AID AVAL BVAL CVAL ---------- ---------- ---------- ---------- 1 A1 B1 C1 2 A2 B2 3 A3
SELECT a.id, a.val AS aval, bc.bval, bc.cval
FROM
atab a
LEFT OUTER JOIN (
SELECT b.id AS bid, b.val AS bval, c.id AS cid, c.val AS cval
FROM btab b LEFT OUTER JOIN ctab c ON (b.id = c.id)
) bc
ON (a.id = bc.bid)
ORDER BY a.id
;
Run Code Online (Sandbox Code Playgroud)
ID AVAL BVAL CVAL ---------- ---------- ---------- ---------- 1 A1 B1 C1 2 A2 B2 3 A3
在这个特定的例子中,似乎两种解决方案都给出了相同的结果.我想不出任何其他数据集会使这些查询返回不同的结果.
检查SQLFiddle:
Mar*_*ery 15
如果你假设你正在加入一个外键,因为你的问题似乎暗示,那么是的,我认为OUTER JOIN保证是联想的,正如Przemyslaw Kruglej所说的那样.
但是,鉴于您实际上没有指定JOIN条件,迂腐正确的答案是否,它们不能保证是关联的.有两种简单的方法可以违反与反常ON
条款的关联性.
这是违反关联性的一种非常便宜的方式,但严格来说,在你的问题中没有任何内容可以禁止它.使用问题中建议的列名称,请考虑以下两个查询:
-- This is legal
SELECT * FROM (A JOIN B ON A.b_id = B.id)
JOIN C ON (A.id = B.id) AND (B.id = C.id)
-- This is not legal
SELECT * FROM A
JOIN (B JOIN C ON (A.id = B.id) AND (B.id = C.id))
ON A.b_id = B.id
Run Code Online (Sandbox Code Playgroud)
底部查询甚至不是有效查询,但顶部查询是.显然,这违反了相关性.
这样,我们的结果集中甚至可以有不同数量的行,具体取决于JOIN的顺序.例如,让B上的JOINing A的条件为A.b_id = B.id
,但是C上的JOINing B的条件B.id IS NULL
.
因此,我们得到这两个查询,输出非常不同:
SELECT * FROM (A LEFT OUTER JOIN B ON A.b_id = B.id)
LEFT OUTER JOIN C ON B.id IS NULL;
SELECT * FROM A
LEFT OUTER JOIN (B LEFT OUTER JOIN C ON B.id IS NULL)
ON A.b_id = B.id;
Run Code Online (Sandbox Code Playgroud)
你可以在这里看到这个:http://sqlfiddle.com/#!2/dd462/3
归档时间: |
|
查看次数: |
10090 次 |
最近记录: |