SQL:将 table 与自身连接起来并允许结果为 null
SQL: Joining a table with itself and allowing null in result
我有一个 table 这样的:
+----+------+-------+
| ID | Type | Value |
+----+------+-------+
| 1 | A | 111 |
+----+------+-------+
| 2 | B | 222 |
+----+------+-------+
| 1 | B | 333 |
+----+------+-------+
| 3 | A | 444 |
+----+------+-------+
| 1 | C | 555 |
+----+------+-------+
ID
不是唯一的,但 ID
与 Type
一起创建了一个唯一的密钥。我希望它 return Type:A
和 Type:B
与 ID:1
的值。这是我使用的代码:
select tA.ID, tA.Value as ValueA, tB.Value as ValueB
from Table_1 tA
join Table_1 tB on tA.ID = tB.ID and (tA.Type = 'A' and tB.Type = 'B')
where tA.ID = 1
这个return是正确的结果:
+----+--------+--------+
| ID | ValueA | ValueB |
+----+--------+--------+
| 1 | 111 | 333 |
+----+--------+--------+
但是如果 ID:1
缺少 Type:B
,就像这样:
+----+------+-------+
| ID | Type | Value |
+----+------+-------+
| 1 | A | 111 |
+----+------+-------+
| 2 | B | 222 |
+----+------+-------+
| 3 | A | 444 |
+----+------+-------+
| 1 | C | 555 |
+----+------+-------+
...我 运行 与上面相同的代码,它 return 是一个 空 结果。
如果缺少 Type:B
,我希望它 return 以下结果:
+----+--------+--------+
| ID | ValueA | ValueB |
+----+--------+--------+
| 1 | 111 | NULL |
+----+--------+--------+
或者如果缺少 Type:A
但有 Type:B
,则结果应为:
+----+--------+--------+
| ID | ValueA | ValueB |
+----+--------+--------+
| 1 | NULL | 333 |
+----+--------+--------+
如果 Type:A 和 Type:B 都缺失,那么 没关系 如果它们 return 为空 或 包含这样的 NULL:
+----+--------+--------+
| ID | ValueA | ValueB |
+----+--------+--------+
| 1 | NULL | NULL |
+----+--------+--------+
我尝试使用 full outer join
:
select tA.ID, tA.Value as ValueA, tB.Value as ValueB
from Table_1 tA
full outer join Table_1 tB on tA.ID = tB.ID and (tA.Type = 'A' and tB.Type = 'B')
where tA.ID = 1
... 但它 return 的结果包括 Type:C
的值,如 ValueA
:
+----+--------+--------+
| ID | ValueA | ValueB |
+----+--------+--------+
| 1 | 111 | NULL |
+----+--------+--------+
| 1 | 555 | NULL |
+----+--------+--------+
如何将我的代码修复为 return 结果,该结果将包含缺失的 Type
的空值?
您可以使用 full join
,但过滤很棘手。这将起作用:
select tA.ID, tA.Value as ValueA, tB.Value as ValueB
from (select tA.*
from Table_1 tA
where tA.ID = 1 and tA.Type = 'A'
) tA full join
(select tB.*
from Table_2 tB
where tB.ID = 1 and tB.Type = 'B'
) tB
on tA.ID = tB.ID ;
我认为这也有效:
select tA.ID, tA.Value as ValueA, tB.Value as ValueB
from Table_1 tA full join
Table_1 tB
on tA.ID = tB.ID
where (tA.ID = 1 or tB.ID = 1) and
(tA.Type = 'A' or tA.Type is null) and
(tA.Type = 'B' or tB.Type is null);
由于 ID
和 Type
对是唯一的,您可以 group by id
并使用条件聚合:
select
id,
max(case type when 'A' then value end) ValueA,
max(case type when 'B' then value end) ValueB
from Table_1
where id = 1 and type in ('A', 'B')
group by id
参见demo。
结果:
| id | ValueA | ValueB |
| --- | ------ | ------ |
| 1 | 111 | 333 |
或:
| id | ValueA | ValueB |
| --- | ------ | ------ |
| 1 | 111 | |
或:
| id | ValueA | ValueB |
| --- | ------ | ------ |
| 1 | | 333 |
针对不同的情况。
我有一个 table 这样的:
+----+------+-------+
| ID | Type | Value |
+----+------+-------+
| 1 | A | 111 |
+----+------+-------+
| 2 | B | 222 |
+----+------+-------+
| 1 | B | 333 |
+----+------+-------+
| 3 | A | 444 |
+----+------+-------+
| 1 | C | 555 |
+----+------+-------+
ID
不是唯一的,但 ID
与 Type
一起创建了一个唯一的密钥。我希望它 return Type:A
和 Type:B
与 ID:1
的值。这是我使用的代码:
select tA.ID, tA.Value as ValueA, tB.Value as ValueB
from Table_1 tA
join Table_1 tB on tA.ID = tB.ID and (tA.Type = 'A' and tB.Type = 'B')
where tA.ID = 1
这个return是正确的结果:
+----+--------+--------+
| ID | ValueA | ValueB |
+----+--------+--------+
| 1 | 111 | 333 |
+----+--------+--------+
但是如果 ID:1
缺少 Type:B
,就像这样:
+----+------+-------+
| ID | Type | Value |
+----+------+-------+
| 1 | A | 111 |
+----+------+-------+
| 2 | B | 222 |
+----+------+-------+
| 3 | A | 444 |
+----+------+-------+
| 1 | C | 555 |
+----+------+-------+
...我 运行 与上面相同的代码,它 return 是一个 空 结果。
如果缺少 Type:B
,我希望它 return 以下结果:
+----+--------+--------+
| ID | ValueA | ValueB |
+----+--------+--------+
| 1 | 111 | NULL |
+----+--------+--------+
或者如果缺少 Type:A
但有 Type:B
,则结果应为:
+----+--------+--------+
| ID | ValueA | ValueB |
+----+--------+--------+
| 1 | NULL | 333 |
+----+--------+--------+
如果 Type:A 和 Type:B 都缺失,那么 没关系 如果它们 return 为空 或 包含这样的 NULL:
+----+--------+--------+
| ID | ValueA | ValueB |
+----+--------+--------+
| 1 | NULL | NULL |
+----+--------+--------+
我尝试使用 full outer join
:
select tA.ID, tA.Value as ValueA, tB.Value as ValueB
from Table_1 tA
full outer join Table_1 tB on tA.ID = tB.ID and (tA.Type = 'A' and tB.Type = 'B')
where tA.ID = 1
... 但它 return 的结果包括 Type:C
的值,如 ValueA
:
+----+--------+--------+
| ID | ValueA | ValueB |
+----+--------+--------+
| 1 | 111 | NULL |
+----+--------+--------+
| 1 | 555 | NULL |
+----+--------+--------+
如何将我的代码修复为 return 结果,该结果将包含缺失的 Type
的空值?
您可以使用 full join
,但过滤很棘手。这将起作用:
select tA.ID, tA.Value as ValueA, tB.Value as ValueB
from (select tA.*
from Table_1 tA
where tA.ID = 1 and tA.Type = 'A'
) tA full join
(select tB.*
from Table_2 tB
where tB.ID = 1 and tB.Type = 'B'
) tB
on tA.ID = tB.ID ;
我认为这也有效:
select tA.ID, tA.Value as ValueA, tB.Value as ValueB
from Table_1 tA full join
Table_1 tB
on tA.ID = tB.ID
where (tA.ID = 1 or tB.ID = 1) and
(tA.Type = 'A' or tA.Type is null) and
(tA.Type = 'B' or tB.Type is null);
由于 ID
和 Type
对是唯一的,您可以 group by id
并使用条件聚合:
select
id,
max(case type when 'A' then value end) ValueA,
max(case type when 'B' then value end) ValueB
from Table_1
where id = 1 and type in ('A', 'B')
group by id
参见demo。
结果:
| id | ValueA | ValueB |
| --- | ------ | ------ |
| 1 | 111 | 333 |
或:
| id | ValueA | ValueB |
| --- | ------ | ------ |
| 1 | 111 | |
或:
| id | ValueA | ValueB |
| --- | ------ | ------ |
| 1 | | 333 |
针对不同的情况。