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 不是唯一的,但 IDType 一起创建了一个唯一的密钥。我希望它 return Type:AType:BID: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);

由于 IDType 对是唯一的,您可以 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    |

针对不同的情况。