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


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.