我正在寻找归档以下内容的方法:
想象一下表A,B:
aID, aID2, avalue
=================
1 , 10 , 'abc'
2 , 20 , 'def'
3 , 30 , 'ghi'
4 , 40 , 'jkl'
bID, bID2, bvalue
=================
1 , 10 , 'mno'
20 , 20 , 'pqr'
3 , 1 , 'stu'
现在看看下面的SQL语句和结果(我在Oracle 11上,但MSSQL应该是相同的):
aID, aID2, avalue, bID , bID2, bvalue
=====================================
1 , 10 , 'abc' , 1 , 10 , 'mno'
2 , 20 , 'def' , NULL, NULL, NULL
3 , 30 , 'ghi' , 3 , 1 , 'stu'
4 , 40 , 'jkl' , NULL, NULL, NULL
aID, aID2, avalue, bID , bID2, bvalue
=====================================
1 , 10 , 'abc' , 1 , 10 , 'mno'
2 , 20 , 'def' , NULL, NULL, NULL
3 , 30 , 'ghi' , NULL, 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 (note 20)
3 , 30 , 'ghi' , 3 , NULL, NULL (note 3)
4 , 40 , 'jkl' , NULL, NULL, NULL
有没有办法让这种行为(保持匹配的部分,NULL不匹配“ON”子句和所有值列的部分)只使用连接而不是反复使用自连接?
如果没有像“保持匹配颜色”这样的关键世界,你会建议用什么方式? 再选择? Selfjoins?
谢谢, Blama
答案 0 :(得分:2)
加入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
答案 1 :(得分:0)
我认为你不会找到一个简单的解决方案,这里的东西适用于你的数据集,但不是很漂亮或有效!
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
不是自我加入,但没有更好,我有兴趣看到更好的解决方案,并了解要求。
答案 2 :(得分:0)
不确定为什么你不能使用/不想要自我加入,但这是一个版本:
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 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
答案 3 :(得分:-1)
为了使这更容易编写(并因此维护),我建议你避免使用外连接,而是将你需要的四个子集联合起来。
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
值(外部联接明确设计为生成)很容易被实际的默认值替换