Как я могу переопределить строки из другой таблицы?

У меня две таблицы:

Таблица А

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

person Farhan    schedule 25.11.2020    source источник
comment
@DaleK Я пробовал объединение и внутреннее / левое соединение.   -  person Farhan    schedule 26.11.2020
comment
Что, если у B есть строка со значением _1 _... появится ли это в результате?   -  person The Impaler    schedule 26.11.2020
comment
@TheImpaler Нет, их идентификаторы должны совпадать. TableB всегда является подмножеством TableA.   -  person Farhan    schedule 26.11.2020
comment
@DaleK Обновленный вопрос   -  person Farhan    schedule 26.11.2020


Ответы (4)


Вы можете оставить присоединение b к a и использовать coalesce, чтобы предпочесть строки b:

SELECT    a.id, COALESCE(b.name, a.name) AS name
FROM      a
LEFT JOIN b ON a.id = b.id
person Mureinik    schedule 25.11.2020

Ты можешь сделать:

select a.id, coalesce(b.name, a.name)
from a left join b on a.id = b.id
person The Impaler    schedule 25.11.2020
comment
вы, вероятно, хотели оставить соединение, поскольку b является подмножеством a, а OP, похоже, хочет, чтобы все строки в a. - person SMor; 26.11.2020

Один метод 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;
person Gordon Linoff    schedule 25.11.2020
comment
Это сложный огромный запрос, я не могу просто использовать его снова. - person Farhan; 26.11.2020
comment
@ Фархан, почему бы и нет? Используйте CTE или временную таблицу для повторного использования результатов. - person Dale K; 26.11.2020
comment
@ Фархан. . . Вы понимаете, что принятый ответ - это второй вопрос здесь. - person Gordon Linoff; 26.11.2020
comment
@GordonLinoff Да, но он разместил это первым. Вы хотите, чтобы я принял ваш ответ? - person Farhan; 30.11.2020
comment
@ Фархан. . . На самом деле, если вы посмотрите на временные метки, эта была опубликована первой. В любом случае, как OP вы можете принять любой ответ, который считаете лучшим. - person Gordon Linoff; 30.11.2020

Более сложный метод использует 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
person Dale K    schedule 25.11.2020