能否根据Oracle SQL中的结果限制左联接的结果?
要将表A连接到表B,以获得表B中特定类型的行。 如果这些类型都不在表B中,则返回表A中的行,表B中的列为null。如果还返回了类型为的行,则不希望返回null行 我尝试使用秩推断方法:能否根据Oracle SQL中的结果限制左联接的结果?,sql,oracle11g,left-join,Sql,Oracle11g,Left Join,要将表A连接到表B,以获得表B中特定类型的行。 如果这些类型都不在表B中,则返回表A中的行,表B中的列为null。如果还返回了类型为的行,则不希望返回null行 我尝试使用秩推断方法: SELECT DISTINCT A.a_id, A.emp, B.b_id, B.id_for_c, C.type, C.rnk FROM A JOIN B on B.b_id = A.a_id Left JOIN ( SELECT b_id, C.type, id_for_c, C.c_id,
SELECT DISTINCT
A.a_id, A.emp, B.b_id, B.id_for_c, C.type, C.rnk
FROM A
JOIN B on B.b_id = A.a_id
Left JOIN ( SELECT b_id, C.type, id_for_c, C.c_id, rnk
FROM ( SELECT B.b_id, B.id_for_c, C.type, C.c_id,
RANK() OVER (PARTITION BY B.b_id
ORDER BY CASE WHEN C.type IS NOT NULL THEN 1 ELSE 2 END) AS rnk
FROM B
LEFT OUTER JOIN C
ON C.c_id = B.id_for_c
AND (C.type=1 or C.type=2)
) C
ORDER BY b_id, C.type, rnk) C
on C.c_id = B.id_for_c;
Data:
create table a (a_id number, emp number);
create table b (b_id number, id_for_c number);
create table c (c_id number, type number);
insert into a values (101, 1000);
insert into a values (102, 2000);
insert into a values (103, 3000);
insert into a values (104, 4000);
insert into b values (101, 25);
insert into b values (101, 75);
insert into b values (102, 50);
insert into b values (103, 75);
insert into b values (104, 25);
insert into b values (104, 75);
insert into c values (25, 1);
insert into c values (50, 2);
insert into c values (75, 3);
尝试:
说明:
(现有查询是with子句中的块)。我使用exists子查询来消除您不想要的内容。您可以使用分析的
rank()
函数来支持空值的非空B值:
SELECT id, type
FROM (
SELECT A.id, B.type,
RANK() OVER (PARTITION BY A.id
ORDER BY CASE WHEN B.type IS NOT NULL THEN 1 ELSE 2 END) AS rnk
FROM A
LEFT OUTER JOIN B
ON B.id = A.id_for_b
AND (B.type=1 or b.type=2)
)
WHERE rnk = 1
ORDER BY id, type;
内部查询添加一个排名列,该列为每个匹配结果提供一个1或2的排名(这两个值)。外部查询然后删除那些排名为2的结果;如果还存在非空值,则这些结果将仅为空值
正如Brian的回答一样,这只会击中你真正的桌子一次
如果任何A都有多个非空值,即类型1和类型2(或者没有非空值,但有多个空值),那么它们都会显示出来;我不确定这两种情况是否适用于您
对于您的三个表变体,我认为您不想加入子查询;当然不想回到您已经使用过的表。希望这能得到您想要的结果:
SELECT a_id, b_id, id_for_c, type, c_id
FROM (
SELECT A.a_id, A.emp, B.b_id, B.id_for_c, C.type, C.c_id,
RANK() OVER (PARTITION BY B.b_id
ORDER BY CASE WHEN C.type IS NOT NULL THEN 1 ELSE 2 END) AS rnk
FROM A
LEFT OUTER JOIN B
ON B.b_id = A.a_id
LEFT OUTER JOIN C
ON C.c_id = B.id_for_c
AND (C.type=1 or C.type=2)
)
WHERE rnk = 1
ORDER BY a_id, b_id;
| A_ID | B_ID | ID_FOR_C | TYPE | C_ID |
|------|------|----------|--------|--------|
| 101 | 101 | 25 | 1 | 25 |
| 102 | 102 | 50 | 2 | 50 |
| 103 | 103 | 75 | (null) | (null) |
| 104 | 104 | 25 | 1 | 25 |
.谢谢Brian。这也帮助了Alex谢谢你。Alex,我们确实有多个空值场景Alex,在试图在代码中实现这种方法时,所有空值都被列为1,即使存在非空值。@user3807647-,所以不确定有什么不同。你能显示一些数据,或者设置一个小提琴来显示问题吗?排名在inn中er查询,对我来说。问题在于如何将其连接回相同的基表。因此,现在有三个表要连接在一起。您希望从这些数据中看到什么结果?您嵌套的
C
没有任何作用,其中的order by
对结果没有影响,因此不确定您要用它做什么。
SELECT a_id, b_id, id_for_c, type, c_id
FROM (
SELECT A.a_id, A.emp, B.b_id, B.id_for_c, C.type, C.c_id,
RANK() OVER (PARTITION BY B.b_id
ORDER BY CASE WHEN C.type IS NOT NULL THEN 1 ELSE 2 END) AS rnk
FROM A
LEFT OUTER JOIN B
ON B.b_id = A.a_id
LEFT OUTER JOIN C
ON C.c_id = B.id_for_c
AND (C.type=1 or C.type=2)
)
WHERE rnk = 1
ORDER BY a_id, b_id;
| A_ID | B_ID | ID_FOR_C | TYPE | C_ID |
|------|------|----------|--------|--------|
| 101 | 101 | 25 | 1 | 25 |
| 102 | 102 | 50 | 2 | 50 |
| 103 | 103 | 75 | (null) | (null) |
| 104 | 104 | 25 | 1 | 25 |