如何覆盖另一个表中的行?
Posted
技术标签:
【中文标题】如何覆盖另一个表中的行?【英文标题】:How can I override rows from another table? 【发布时间】:2020-11-25 21:40:25 【问题描述】:我有两张桌子:
表A
ID Name
-- ----
1 aaa
2 bbb
3 ccc
4 ddd
表B
ID Name
-- --------
3 WWXXYYZZ
我想从两个表中进行选择,但跳过 TableB 中存在的行。结果应如下所示:
ID Name
-- --------
1 aaa
2 bbb
3 WWXXYYZZ
4 ddd
我尝试过union
和join
,但不知道如何实现。
-- Did not work
select *
from TableA
union
select *
from TableB
-- Did not work
select *
from
(
select *
from TableA
) x
join
(
select *
from TableB
) y
on x.ID = y.ID
【问题讨论】:
@DaleK 我试过联合和内/左连接。 如果 B 有一行值为5
... 会出现在结果中吗?
@TheImpaler 不,他们的 ID 必须匹配。 TableB 始终是 TableA 的子集。
@DaleK 更新问题
【参考方案1】:
您可以离开加入 b
到 a
,并使用 coalesce
来选择 b
的行:
SELECT a.id, COALESCE(b.name, a.name) AS name
FROM a
LEFT JOIN b ON a.id = b.id
【讨论】:
【参考方案2】:你可以这样做:
select a.id, coalesce(b.name, a.name)
from a left join b on a.id = b.id
【讨论】:
您可能打算离开联接,因为 b 是 a 的子集,而 OP 似乎想要 a 中的所有行。【参考方案3】:一种方法是union all
:
select b.*
from b
union all
select a.*
from a
where not exists (select 1 from a where a.id = b.id);
您还可以从 a
中选择并使用 b 中的值覆盖:
select a.id, coalesce(b.name, a.name) as name
from a left join
b
on a.id = b.id;
【讨论】:
这是一个复杂的大查询,我不能再次使用它。 @Farhan 为什么不呢?使用 CTE 或临时表来重用结果。 @Farhan 。 . .你意识到你接受的答案是这里的第二个查询。 @GordonLinoff 是的,但他先发布了。你想让我接受你的回答吗? @Farhan 。 . .实际上,如果你看一下时间戳,这个是第一个发布的。无论如何,作为 OP,您可以接受您认为最好的任何答案。【参考方案4】:更复杂的方法使用ROW_NUMBER
,如果您的查询比显示的复杂得多,这可能是必要的。它还处理了 TableB 中存在行但 TableA 中不存在行的情况(从您的问题中不清楚)。
DECLARE @TableA TABLE (id INT, [Name] VARCHAR(12));
DECLARE @TableB TABLE (id INT, [Name] VARCHAR(12));
INSERT INTO @TableA (id, [Name])
VALUES
(1, 'aaa'),
(2, 'bbb'),
(3, 'ccc'),
(4, 'ddd');
INSERT INTO @TableB (id, [Name])
VALUES
(3, 'WWXXYYZZ'),
(5, 'TTTGGG');
SELECT id, [Name]
FROM (
SELECT id, [Name]
, ROW_NUMBER() OVER (PARTITION BY id ORDER BY [Priority] DESC) Rn
FROM (
SELECT id, [Name], 0 [Priority]
FROM @TableA
UNION ALL
SELECT id, [Name], 1 [Priority]
FROM @TableB
) X
) Y
WHERE Rn = 1;
返回:
1 aaa
2 bbb
3 WWXXYYZZ
4 ddd
5 TTTGGG
【讨论】:
以上是关于如何覆盖另一个表中的行?的主要内容,如果未能解决你的问题,请参考以下文章
MySQL - 如何选择表中的行,其中 id 值位于另一个表中的逗号分隔字段中?