【问题标题】:Union of SQL tables, but only taking the first instance of an IDSQL 表的联合,但仅采用 ID 的第一个实例
【发布时间】:2012-11-08 15:21:11
【问题描述】:

我有三个具有相同列的表,我需要将它们合并到一个表中。一些 ID 出现在多个表中,我需要首先使用编号最小的表中的 ID,并在任何后续表中忽略该 ID。注意只有ID相同,表之间没有重复行。

所以举个例子,这三个表需要转化为最终表:

**Table 1**
+----+----+----+
| ID | C1 | C2 |
+----+----+----+
| 01 | AA | BB |
| 02 | CC | DD |
| 03 | EE | FF |
+----+----+----+

**Table 2**
+----+----+----+
| ID | C1 | C2 |
+----+----+----+
| 03 | GG | HH |
| 04 | II | JJ |
| 05 | KK | LL |
+----+----+----+

**Table 3**
+----+----+----+
| ID | C1 | C2 |
+----+----+----+
| 01 | MM | NN |
| 04 | OO | PP |
| 06 | QQ | RR |
+----+----+----+

**Resulting Table**
+----+----+----+
| ID | C1 | C2 |
+----+----+----+
| 01 | AA | BB |
| 02 | CC | DD |
| 03 | EE | FF |
| 04 | II | JJ |
| 05 | KK | LL |
| 06 | QQ | RR |
+----+----+----+

我对使用左连接和“IS NULL”条件的解决方案有一个模糊的想法,但这可能会很快变得复杂,尤其是在表数量增加的情况下。

有没有办法只在一列上指定重复项,而不是在整行上?

【问题讨论】:

  • 您使用的是什么 DBMS?
  • Access 中的 T-SQL。我想解决问题的另一种方式是我想要所有表 1,然后只需要表 2 中其 ID 不存在于表 1 中的行,然后只有表 3 中其 ID 不存在的行见表 1 和表 2。
  • 哎呀,在看到你在Access中做之前我写了答案......我会重写它......

标签: sql ms-access duplicates union


【解决方案1】:

由于你使用的是Access,你可以使用FIRST函数,我想你只需要这个:

SELECT ID, First(C1) As C1, First(C2) as C2
FROM (
  SELECT * FROM Table1 UNION SELECT * FROM Table2 UNION SELECT * FROM Table3 )
GROUP BY ID

【讨论】:

  • 哇...这是实现这一目标的优雅方式!
【解决方案2】:

如果不计算 NULL 值,则可以应用此逻辑:

  • 获取 3 个表中存在的所有 ID(这是联合部分)
  • 左连接所有表,并使用COALESCE,找到每列的第一个非空值

访问 MS SQL:

select ids.ID, COALESCE(t1.C1,t2.C1,t3.C1) C1, COLAESCE(t1.C2,t2.C2,t3.C2) C2 
from
(SELECT ID FROM Table1
UNION
SELECT ID FROM Table2
UNION
SELECT ID FROM Table3) AS ids
left join Table1 t1 on ids.id=t1.id
left join Table2 t2 on ids.id=t2.id
left join Table3 t3 on ids.id=t3.id

但可悲的是访问doesn't support COALESCE...它有新西兰:

select ids.ID, NZ(NZ(t1.C1,t2.C1),t3.C1) C1, NZ(NZ(t1.C2,t2.C2),t3.C2) C2 
from
(SELECT ID FROM Table1
UNION
SELECT ID FROM Table2
UNION
SELECT ID FROM Table3) AS ids
left join Table1 t1 on ids.id=t1.id
left join Table2 t2 on ids.id=t2.id
left join Table3 t3 on ids.id=t3.id

(虽然目前手头没有 MS Access,但我无法对其进行测试)

旁注:在 Oracle 中,您可以这样做(我不想删除它):

select ids.ID, NVL(NVL(t1.C1,t2.C1),t3.C1) C1, NVL(NVL(t1.C2,t2.C2),t3.C2) from
(SELECT ID FROM Table1
UNION
SELECT ID FROM Table2
UNION
SELECT ID FROM Table3) ids
left join Table1 t1 on ids.id=t1.id
left join Table2 t2 on ids.id=t2.id
left join Table3 t3 on ids.id=t3.id

如果 NULL 值被认为是有效的,那就有点问题了,就像 MS Access doesn't support CASE-WHEN statements - 除非在 VBA 中...

在 Oracle 中,这样做可以:

select ids.ID,
CASE WHEN t1.ID IS NOT NULL THEN t1.C1 
     WHEN t1.ID IS NULL AND t2.ID IS NOT NULL THEN t2.C1
     ELSE t3.C1 END C1,
CASE WHEN t1.ID IS NOT NULL THEN t1.C2 
     WHEN t1.ID IS NULL AND t2.ID IS NOT NULL THEN t2.C2
     ELSE t3.C2 END C2
from
(SELECT ID FROM Table1
UNION
SELECT ID FROM Table2
UNION
SELECT ID FROM Table3) AS ids
left join Table1 t1 on ids.id=t1.id
left join Table2 t2 on ids.id=t2.id
left join Table3 t3 on ids.id=t3.id

【讨论】:

  • 不能投票,因为我没有足够的声誉,不管是什么,但明天会尝试,让你知道我的进展如何。谢谢, Null 值不应该存在,所以这应该有效。 :)
猜你喜欢
  • 1970-01-01
  • 2019-01-15
  • 2017-12-31
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-06-13
相关资源
最近更新 更多