SQL外部联接:";“部分空”-通缉犯
我正在寻找一种归档以下内容的方法: 想象一下表A、B: A: B: 现在看看下面的SQL语句和结果(我使用的是Oracle 11,但MSSQL应该是相同的): 从(A.aID=B.bID)上的左侧外部联接B中选择A.*,B.* 从(A.aID=B.bID和A.aID2=B.bID2)上的左侧外部联接B中选择A.*,B.* 到目前为止还不错 我正在寻找一份声明(尽可能简单),它让我得到以下信息: 组合代码:从左侧外部联接B上选择A.*,B.*(A.aID=B.bID和A.aID2=B.bID2保持匹配列) 有没有办法只使用连接而不反复使用自连接来获得这种行为(保持匹配部分、NULL不匹配“ON”子句和所有值列的部分) 如果没有像“保持匹配COLS”这样的keyworld,你会建议什么方法? 再选择?自联接 谢谢,SQL外部联接:";“部分空”-通缉犯,sql,database,oracle,left-join,outer-join,Sql,Database,Oracle,Left Join,Outer Join,我正在寻找一种归档以下内容的方法: 想象一下表A、B: A: B: 现在看看下面的SQL语句和结果(我使用的是Oracle 11,但MSSQL应该是相同的): 从(A.aID=B.bID)上的左侧外部联接B中选择A.*,B.* 从(A.aID=B.bID和A.aID2=B.bID2)上的左侧外部联接B中选择A.*,B.* 到目前为止还不错 我正在寻找一份声明(尽可能简单),它让我得到以下信息: 组合代码:从左侧外部联接B上选择A.*,B.*(A.aID=B.bID和A.aID2=B.bID2保持
Bumma我不认为您会找到一个简单的解决方案,这里有一些东西可以在您的数据集上运行,但不美观也不高效
create table A ( aID int, aID2 int, avalue char(3) )
create table B ( bID int, bID2 int, bvalue char(3) )
insert into A VALUES (1 , 10 , 'abc')
insert into A VALUES (2 , 20 , 'def')
insert into A VALUES (3 , 30 , 'ghi')
insert into A VALUES (4 , 40 , 'jkl')
insert into B VALUES (1 , 10 , 'mno')
insert into B VALUES (20 , 20 , 'pqr')
insert into B VALUES (3 , 1 , 'stu')
select distinct
A.*,
COALESCE(B1.bID,B2.bID) as bID,
COALESCE(B1.bID2,B3.bID2) as BID2,
B1.bvalue
from A
left outer join
B B1
on
A.aID = B1.bID
AND
A.aID2 = B1.bID2
left outer join
B B2
on
A.aID = B2.bID
left outer join
B B3
on
A.aID2 = B3.bID2
aID, aID2, avalue, bID , bID2, bvalue
=====================================
1 , 10 , 'abc' , 1 , 10 , 'mno'
2 , 20 , 'def' , NULL, 20 , NULL
3 , 30 , 'ghi' , 3 , NULL, NULL
4 , 40 , 'jkl' , NULL, NULL, NULL
不完全是自连接,但没有更好的,我希望看到一个更好的解决方案,并了解需求。我不认为您会找到一个简单的解决方案,这里有一些东西可以在您的数据集上使用,但不美观也不高效
create table A ( aID int, aID2 int, avalue char(3) )
create table B ( bID int, bID2 int, bvalue char(3) )
insert into A VALUES (1 , 10 , 'abc')
insert into A VALUES (2 , 20 , 'def')
insert into A VALUES (3 , 30 , 'ghi')
insert into A VALUES (4 , 40 , 'jkl')
insert into B VALUES (1 , 10 , 'mno')
insert into B VALUES (20 , 20 , 'pqr')
insert into B VALUES (3 , 1 , 'stu')
select distinct
A.*,
COALESCE(B1.bID,B2.bID) as bID,
COALESCE(B1.bID2,B3.bID2) as BID2,
B1.bvalue
from A
left outer join
B B1
on
A.aID = B1.bID
AND
A.aID2 = B1.bID2
left outer join
B B2
on
A.aID = B2.bID
left outer join
B B3
on
A.aID2 = B3.bID2
aID, aID2, avalue, bID , bID2, bvalue
=====================================
1 , 10 , 'abc' , 1 , 10 , 'mno'
2 , 20 , 'def' , NULL, 20 , NULL
3 , 30 , 'ghi' , 3 , NULL, NULL
4 , 40 , 'jkl' , NULL, NULL, NULL
不完全是自联接,但也不是更好,我希望看到更好的解决方案,并了解需求。在Id或Id2上联接,然后在select子句中选择性地取消结果 设置测试表和数据:
set null 'NULL'
create table a (aId number
, aId2 number
, aValue varchar2(4));
insert into a values (1, 10, 'abc');
insert into a values (2, 20, 'def');
insert into a values (3, 30, 'ghi');
insert into a values (4, 40, 'jkl');
create table b (bId number
, bId2 number
, bValue varchar2(4));
insert into b values (1, 10, 'mno');
insert into b values (20, 20, 'pqr');
insert into b values (3, 1, 'stu');
commit;
查询:
select A.*
, case when A.aId = B.bId then B.bId end as bId
, case when A.aId2 = B.bID2 then B.bId2 end as bId2
, case when A.aId = B.bId
and A.aId2 = B.bId2 then bValue end as bValue
from A
left outer join B on A.aID = B.bId or A.aId2 = B.bId2;
结果:
AID AID2 AVAL BID BID2 BVAL
---------- ---------- ---- ---------- ---------- ----
1 10 abc 1 10 mno
2 20 def NULL 20 NULL
3 30 ghi 3 NULL NULL
4 40 jkl NULL NULL NULL
aID aID2 avalue bID bID2 bvalue
1 10 abc 1 10 mno
2 20 def NULL 20 NULL
3 30 ghi 3 NULL NULL
4 40 jkl NULL NULL NULL
在Id或Id2上联接,然后在select子句中有选择地将结果置空 设置测试表和数据:
set null 'NULL'
create table a (aId number
, aId2 number
, aValue varchar2(4));
insert into a values (1, 10, 'abc');
insert into a values (2, 20, 'def');
insert into a values (3, 30, 'ghi');
insert into a values (4, 40, 'jkl');
create table b (bId number
, bId2 number
, bValue varchar2(4));
insert into b values (1, 10, 'mno');
insert into b values (20, 20, 'pqr');
insert into b values (3, 1, 'stu');
commit;
查询:
select A.*
, case when A.aId = B.bId then B.bId end as bId
, case when A.aId2 = B.bID2 then B.bId2 end as bId2
, case when A.aId = B.bId
and A.aId2 = B.bId2 then bValue end as bValue
from A
left outer join B on A.aID = B.bId or A.aId2 = B.bId2;
结果:
AID AID2 AVAL BID BID2 BVAL
---------- ---------- ---- ---------- ---------- ----
1 10 abc 1 10 mno
2 20 def NULL 20 NULL
3 30 ghi 3 NULL NULL
4 40 jkl NULL NULL NULL
aID aID2 avalue bID bID2 bvalue
1 10 abc 1 10 mno
2 20 def NULL 20 NULL
3 30 ghi 3 NULL NULL
4 40 jkl NULL NULL NULL
不确定为什么不能使用/不希望使用自联接,但以下是一个版本:
SELECT a.aID,
a.aID2,
a.avalue,
b1.bID,
b2.bID2,
CASE WHEN b1.bID = b2.bID AND b1.bID2 = b2.bID2 THEN b1.bvalue ELSE NULL END as bvalue
FROM A a
LEFT OUTER JOIN B b1
ON (a.aID = b1.bID)
LEFT OUTER JOIN B b2
ON (a.aID2 = b2.bID2)
结果:
AID AID2 AVAL BID BID2 BVAL
---------- ---------- ---- ---------- ---------- ----
1 10 abc 1 10 mno
2 20 def NULL 20 NULL
3 30 ghi 3 NULL NULL
4 40 jkl NULL NULL NULL
aID aID2 avalue bID bID2 bvalue
1 10 abc 1 10 mno
2 20 def NULL 20 NULL
3 30 ghi 3 NULL NULL
4 40 jkl NULL NULL NULL
不确定为什么不能使用/不希望使用自联接,但以下是一个版本:
SELECT a.aID,
a.aID2,
a.avalue,
b1.bID,
b2.bID2,
CASE WHEN b1.bID = b2.bID AND b1.bID2 = b2.bID2 THEN b1.bvalue ELSE NULL END as bvalue
FROM A a
LEFT OUTER JOIN B b1
ON (a.aID = b1.bID)
LEFT OUTER JOIN B b2
ON (a.aID2 = b2.bID2)
结果:
AID AID2 AVAL BID BID2 BVAL
---------- ---------- ---- ---------- ---------- ----
1 10 abc 1 10 mno
2 20 def NULL 20 NULL
3 30 ghi 3 NULL NULL
4 40 jkl NULL NULL NULL
aID aID2 avalue bID bID2 bvalue
1 10 abc 1 10 mno
2 20 def NULL 20 NULL
3 30 ghi 3 NULL NULL
4 40 jkl NULL NULL NULL
为了便于编写(因此也便于维护),我建议您避免外部联接,而是将所需的四个子集联合起来
SELECT A.*, B.* FROM A INNER JOIN B ON (A.aID = B.bID AND A.aID2 = B.bID2)
UNION
SELECT A.*, NULL, NULL, NULL
FROM A
WHERE NOT EXISTS (
SELECT *
FROM B
WHERE (A.aID = B.bID)
)
AND NOT EXISTS (
SELECT *
FROM B
WHERE (A.aID2 = B.bID2)
)
UNION
SELECT A.*, B.bID, NULL, NULL
FROM A INNER JOIN B ON (A.aID = B.bID)
AND NOT EXISTS (
SELECT *
FROM B
WHERE (A.aID2 = B.bID2)
)
UNION
SELECT A.*, NULL, B.bID2, NULL
FROM A INNER JOIN B ON (A.aID2 = B.bID2)
WHERE NOT EXISTS (
SELECT *
FROM B
WHERE (A.aID = B.bID)
);
这种方法的优点是使用关系运算符join、semi-difference和union,允许那些非关系的
NULL
值(外部联接被明确设计为生成这些值)轻松地替换为实际的默认值。为了使这更易于编写(并因此维护),我建议您避免外部联接,而是将所需的四个子集合并
SELECT A.*, B.* FROM A INNER JOIN B ON (A.aID = B.bID AND A.aID2 = B.bID2)
UNION
SELECT A.*, NULL, NULL, NULL
FROM A
WHERE NOT EXISTS (
SELECT *
FROM B
WHERE (A.aID = B.bID)
)
AND NOT EXISTS (
SELECT *
FROM B
WHERE (A.aID2 = B.bID2)
)
UNION
SELECT A.*, B.bID, NULL, NULL
FROM A INNER JOIN B ON (A.aID = B.bID)
AND NOT EXISTS (
SELECT *
FROM B
WHERE (A.aID2 = B.bID2)
)
UNION
SELECT A.*, NULL, B.bID2, NULL
FROM A INNER JOIN B ON (A.aID2 = B.bID2)
WHERE NOT EXISTS (
SELECT *
FROM B
WHERE (A.aID = B.bID)
);
这种方法的优点是使用关系运算符join、semi-difference和union,允许那些非关系的
NULL
值(外部联接专门用于生成)轻松替换为实际的默认值。如果Id或Id2不匹配,则不会将bValue返回为NULL。请参见预期结果的第2行和第3行。我同意,要求是不同的,最好有更多的上下文。如果Id或Id2不匹配,则不会将bValue返回为null。请参见预期结果的第2行和第3行。我同意,要求是不同的,最好有更多的上下文。因为我对Stackoverflow比较陌生,我不知道更好的problemspecification应该属于哪里。我把它写在我的帖子的回复里。感谢Bullaas,我对Stackoverflow还比较陌生,我不知道更好的问题规范应该属于哪里。我把它写在我的帖子的回复里。谢谢你