合并具有不同列数的两个表


106

我有两个表(表A和表B)。

它们具有不同的列数-假设表A具有更多列。

如何合并这两个表,并为表B没有的列获取空值?

Answers:


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:您可以像将isull(ColumnName,0)用作ColumnName或将isull(ColumnName,'-')作为ColumnName一样。
康坎2014年

3
我意识到该解决方案也可以工作,而不必列出所有列。因此,代替Select Col1, Col2, Col3, Null as Col4, Null as Col5 from Table2,一个人也可以做Select *, Null as Col4, Null as Col5 from Table2
Pratik Patel

对于null值,此技巧对我有用:'SomeString'作为DummyColumn。基本上,您只需将NULL替换为某些值即可。与groupby一起使用时,此方法也有效。
Saurabh Jain

8

我来到这里,并按照上面的答案。但是数据类型的顺序不匹配会导致错误。以下来自另一个答案的描述将非常有用。

上面的结果是否与表中的列顺序相同?因为oracle在列顺序方面很严格。下面的示例产生一个错误:

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:表达式必须具有与相应表达式相同的数据类型

如您所见,错误的根本原因在于使用*作为列列表说明符所隐含的不匹配列顺序。通过显式输入列列表,可以轻松避免此类错误:

从test1_1790中选择col_a,col_b,col_c,全部从test2_1790中选择col_a,col_b,col_c;对于此错误,更常见的情况是您无意间交换(或移位)了SELECT列表中的两个或更多列:

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

或者,如果上述方法不能解决您的问题,那么如何在像这样的列中创建ALIAS:(查询与您的查询不同,但是这里的重点是如何在列中添加别名。)

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

通常,在使用基于集合的运算符时,您需要具有相同的列数,因此Kangkan的答案是正确的。

SAS SQL具有特定的运算符来处理这种情况:

SAS(R)9.3 SQL过程用户指南

对应(CORR)关键字

仅当指定了set运算符时,才使用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;对于非可为空的类型,.Net默认值为(例如,对于int为0)。

按名字

与OUTER一起使用时是必需的。该子句表明并集不是根据位置而是根据列的名称来匹配值。如果未指定BY NAME子句,则匹配在位置上进行。

如果ON子句包含“ *”符号(可以将其指定为列表的最后一个或唯一的成员),则允许使用ON子句中的名称之外的其他名称匹配,并且结果的列将包含它们出现在左参数中的顺序。

和代码:

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

编辑:

KQL支持外部联合的概念:

类:

内部-结果具有所有输入表共有的列子集。

外部-结果包含所有输入中出现的所有列。输入行未定义的单元格设置为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中实现这一目标?
KetanVaghasiya

@KetanVaghasiya据我所知,只有SAS SQL和U-SQL支持此概念。
Lukasz Szozda

-1

如果只有1行,则可以使用join

Select t1.Col1, t1.Col2, t1.Col3, t2.Col4, t2.Col5 from Table1 t1 join Table2 t2;

两个1行表(两个带有一个元组的多集关系)的并集将在结果关系中具有两行(元组)。在关系代数(不是SQL)中,联合结果可能是一行,尽管只有两个输入关系包含相同的元组,例如。一元组关系的自统一。
罗伯特·蒙菲拉
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.