#sql #oracle #oracle12c
Вопрос:
У меня есть 2 разные таблицы с одинаковой структурой данных, таблицы A и B, можно ли получить значения из A, а затем из B, где, если запись идентификатора существует в B, она заменяет значение, полученное в A?
Пример:
select '1' as id, 'Bob' as "user" from dual
union
select '1' as id, 'Alice' as "user" from dual
Это возвращает:
1 Bob
1 Alice
Если id
то же самое во втором выборе, я хотел бы иметь только одну строку:
1 Alice
Комментарии:
1. Для меня это звучит как что-то вроде внешнего соединения, а не союза.
2. Выполните ОБЪЕДИНЕНИЕ с обновлением.
3. если ваша таблица такова
user
, нет смысла выполнятьunion
операцию, чтобы получить все идентификаторы с вашим состоянием. Что это значит в первую очередь и во вторую очередь для вас?4. @Джеймс «пользователь» — это не таблица, это имя столбца. Две таблицы представлены в примере встроенными операторами select, выбирающими из «dual», поскольку Oracle не разрешает оператор select без таблицы.
Ответ №1:
Вместо ОБЪЕДИНЕНИЯ вам нужно «ПОЛНОЕ ВНЕШНЕЕ СОЕДИНЕНИЕ», которое даст вам три типа строк:
- Строки, в которых обе таблицы имеют совпадающий идентификатор со значениями из обеих таблиц (строки, которые вернет ВНУТРЕННЕЕ СОЕДИНЕНИЕ)
- Строки, в которых только таблица A имеет этот идентификатор, с нулем для столбцов таблицы B (дополнительные строки, которые вернет ЛЕВОЕ ВНЕШНЕЕ СОЕДИНЕНИЕ)
- Строки, где только таблица B имеет этот идентификатор, с нулем для столбцов таблицы A (дополнительные строки, которые вернет ПРАВОЕ ВНЕШНЕЕ СОЕДИНЕНИЕ)
Затем вы можете использовать COALESCE для получения значений из B, если они присутствуют (первый и второй типы строк), и A, если нет (третий тип строк).
Так что для вашего примера:
Select
Coalesce(B.id, A.id) as id,
Coalesce(B."user", A."user") as "user"
From
(select '1' as id, 'Bob' as "user" from dual) as A
Full Outer Join
(select '1' as id, 'Alice' as "user" from dual) as B
On B.id = A.id
Который возвращает:
ID | пользователь |
---|---|
1 | Алиса |
(Примечание: протестировано на SQL Server, удалив «из dual», потому что у меня нет базы данных Oracle для тестирования.)
Ответ №2:
Один из способов сделать это -:
select '1' as id, 'Bob' as "user" from table_A
where id not in (select id from table_B)
union all
select '1' as id, 'Alice' as "user" from table_B
Ответ №3:
Вы можете попробовать этот способ, используя ROW_NUMBER() над (РАЗДЕЛ ПО порядку идентификаторов по вкладке), где «вкладка» — это имя таблицы, в этом примере данные из table_a получат приоритет и будут собраны.
create table table_a as
(
select '1' as id, 'Bob' as "user" from dual
UNION
select '2' as id, 'Jack' as "user" from dual
) ;
create table table_b as
(
select '1' as id, 'Alice' as "user" from dual -- table
UNION
select '3' as id, 'John' as "user" from dual -- table
) ;
select * from (
select ROW_NUMBER() over (PARTITION BY id order by tab) rnum,id, "user"
from(
select id, "user", 'A' tab from table_a
union all
select id, "user", 'b' tab from table_b
)
) WHERE RNUM = 1;