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


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
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.