Объединение двух таблиц с разным количеством столбцов

106

У меня есть две таблицы (таблица A и таблица B).

У них разное количество столбцов - скажем, в таблице A больше столбцов.

Как я могу объединить эти две таблицы и получить null для столбцов, которых нет в таблице B?

Джек Када
источник

Ответы:

216

Добавьте дополнительные столбцы как null для таблицы с меньшим количеством столбцов, например

Select Col1, Col2, Col3, Col4, Col5 from Table1
Union
Select Col1, Col2, Col3, Null as Col4, Null as Col5 from Table2
Кангкан
источник
6
Есть ли способ заполнить значение по умолчанию для столбца Null?
Hans
3
@Hans: вы можете сделать что-то вроде isnull (ColumnName, 0) как ColumnName или isnull (ColumnName, '-') как ColumnName или что-то подобное.
Kangkan
3
Я понял, что это решение также работает без необходимости перечислять все столбцы. Таким образом , вместо того Select Col1, Col2, Col3, Null as Col4, Null as Col5 from Table2, можно также сделать, Select *, Null as Col4, Null as Col5 from Table2.
Pratik Patel
Для нулевого значения у меня сработал этот прием: SomeString как DummyColumn. По сути, вы просто заменяете NULL некоторым значением. Это также работало при использовании с groupby.
Саураб Джайн
8

Я пришел сюда и последовал приведенному выше ответу. Но несоответствие в порядке типа данных вызвало ошибку. Приведенное ниже описание из другого ответа пригодится.

Соответствуют ли приведенные выше результаты последовательности столбцов в вашей таблице? потому что оракул строг к порядку столбцов. в приведенном ниже примере возникает ошибка:

create table test1_1790 (
col_a varchar2(30),
col_b number,
col_c date);

create table test2_1790 (
col_a varchar2(30),
col_c date,
col_b number);

select * from test1_1790
union all
select * from test2_1790;

ORA-01790: выражение должно иметь тот же тип данных, что и соответствующее выражение

Как видите, основная причина ошибки заключается в несоответствии порядка столбцов, что подразумевается использованием * в качестве спецификатора списка столбцов. Ошибок этого типа можно легко избежать, явно указав список столбцов:

выберите col_a, col_b, col_c из test1_1790 union, все выберите col_a, col_b, col_c из test2_1790; Более частым сценарием этой ошибки является случай, когда вы случайно меняете местами (или сдвигаете) два или более столбца в списке SELECT:

select col_a, col_b, col_c from test1_1790
union all
select col_a, col_c, col_b from test2_1790;

ИЛИ, если приведенное выше не решает вашу проблему, как насчет создания АЛИАСА в столбцах, подобных этому: (запрос не такой, как ваш, но суть в том, как добавить псевдоним в столбец.)

SELECT id_table_a, 
       desc_table_a, 
       table_b.id_user as iUserID, 
       table_c.field as iField
UNION
SELECT id_table_a, 
       desc_table_a, 
       table_c.id_user as iUserID, 
       table_c.field as iField
Ананд Варки Филипс
источник
Мне пришлось использовать то же самое, но я добавил a.col_name и b.col_name для ненулевых столбцов. Для нулевых столбцов мне пришлось использовать: NULL AS col_name1, NULL AS col_name2 и т. Д.
Scott R
1
обратите внимание: SELECT * UNION можно объединять в цепочку несколько раз; примечание WHERE фильтры могут использоваться в каждом предложении SELECT
mirekphd
1

Обычно, когда вы используете операторы на основе наборов, вам нужно иметь одинаковое количество столбцов, поэтому ответ Кангкана правильный.

В SAS SQL есть специальный оператор для обработки этого сценария:

SAS (R) 9.3 Руководство пользователя процедуры SQL

CORRESPONDING (CORR) ключевое слово

Ключевое слово CORRESPONDING используется только в том случае, если указан оператор набора. CORR заставляет PROC SQL сопоставлять столбцы в табличных выражениях по имени, а не по порядковому номеру. Столбцы, имена которых не совпадают, исключаются из таблицы результатов, за исключением оператора OUTER UNION.

SELECT * FROM tabA
OUTER UNION CORR
SELECT * FROM tabB;

Для:

+---+---+
| a | b |
+---+---+
| 1 | X |
| 2 | Y |
+---+---+

OUTER UNION CORR

+---+---+
| b | d |
+---+---+
| U | 1 |
+---+---+

<=>

+----+----+---+
| a  | b  | d |
+----+----+---+
|  1 | X  |   |
|  2 | Y  |   |
|    | U  | 1 |
+----+----+---+

U-SQL поддерживает аналогичную концепцию:

ВНЕШНИЙ СОЮЗ ПО ИМЕНИ (*)

ВНЕШНИЙ

требуется предложение BY NAME и список ON. В отличие от других выражений набора, схема вывода OUTER UNION включает как совпадающие, так и несовпадающие столбцы с обеих сторон. Это создает ситуацию, когда каждая строка, идущая с одной стороны, имеет «недостающие столбцы», которые присутствуют только на другой стороне. Для таких столбцов для «отсутствующих ячеек» предоставляются значения по умолчанию. Значения по умолчанию - null для типов, допускающих значение NULL, и значение по умолчанию .Net для типов, не допускающих значения NULL (например, 0 для типов int).

ПО ИМЕНИ

требуется при использовании с OUTER. Предложение указывает, что объединение сопоставляет значения не на основе позиции, а по имени столбцов. Если предложение BY NAME не указано, сопоставление выполняется позиционно.

Если предложение ON включает в себя символ «*» (он может быть указан как последний или единственный член списка), то разрешены дополнительные совпадения имен помимо тех, которые указаны в предложении ON, и столбцы результата включают все совпадающие столбцы в порядок их присутствия в левом аргументе.

И код:

@result =    
    SELECT * FROM @left
    OUTER UNION BY NAME ON (*) 
    SELECT * FROM @right;

РЕДАКТИРОВАТЬ:

Концепция внешнего объединения поддерживается KQL :

Добрый:

inner - результат имеет подмножество столбцов, общих для всех входных таблиц.

external - результат содержит все столбцы, которые встречаются в любом из входов. Ячейкам, которые не были определены входной строкой, устанавливается значение NULL.

Пример:

let t1 = datatable(col1:long, col2:string)  
[1, "a",  
2, "b",
3, "c"];
let t2 = datatable(col3:long)
[1,3];
t1 | union kind=outer t2;

Вывод:

+------+------+------+
| col1 | col2 | col3 |
+------+------+------+
|    1 | a    |      |
|    2 | b    |      |
|    3 | c    |      |
|      |      |    1 |
|      |      |    3 |
+------+------+------+

демо

Лукаш Шозда
источник
Любая идея, как добиться этого в SQL?
Кетан Вагасия 05
@KetanVaghasiya Насколько мне известно, эту концепцию поддерживают только SAS SQL и U-SQL.
Лукаш Шозда 05
-1

если только 1 строка, вы можете использовать соединение

Select t1.Col1, t1.Col2, t1.Col3, t2.Col4, t2.Col5 from Table1 t1 join Table2 t2;
Сай Сай
источник
Объединение двух однострочных таблиц (два отношения мультимножества, каждая с одним кортежем) будет иметь две строки (кортежи) в результирующем отношении. В реляционной алгебре (которой не является SQL) результатом объединения может быть одна строка, но только если два входных отношения содержат идентичный кортеж, например. самосоединение однокортежного отношения.
Роберт Монфера 03