我有两个表(表A和表B)。
它们具有不同数量的列-比如说,表A有更多的列。
如何将这两个表联合起来,并且对于表B没有的列返回null值?
对于列较少的表格,可以添加额外的空列,如下所示:
Select Col1, Col2, Col3, Col4, Col5 from Table1
Union
Select Col1, Col2, Col3, Null as Col4, Null as Col5 from Table2
Select Col1, Col2, Col3, Null as Col4, Null as Col5 from Table2
这样的语句,我们也可以使用 Select *, Null as Col4, Null as Col5 from Table2
。请注意,这两个语句的意思是相同的。 - Pratik PatelSELECT *, Null as Col3, Null as Col4
替换SELECT Col1,Col2,Null as Col3,Null as Col4,Col5
。 - Aidin我来到这里并按照上面的答案进行操作。但是由于数据类型的顺序不匹配,导致出现错误。下面来自另一个答案的描述将会很有帮助。
你的结果是否与表中列的顺序相同?因为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: 表达式必须与相应表达式具有相同的数据类型
正如您所看到的,错误的根本原因在于使用“*”作为列列表指定符所暗示的列顺序不匹配。通过显式输入列列表,可以轻松避免此类错误:
select col_a, col_b, col_c from test1_1790 union all select col_a, col_b, col_c from 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
通常情况下,当你使用基于集合的运算符时,需要拥有相同数量的列,所以Kangkan's answer是正确的。
SAS SQL有特定的运算符来处理这种情况:
SAS(R) 9.3 SQL Procedure User's Guide
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支持类似的概念:
OUTER
需要BY NAME子句和ON列表。与其他集合表达式相反,OUTER UNION的输出模式包括来自两侧的匹配列和非匹配列。这会创建一种情况,即来自其中一侧的每行都有“缺失列”,这些列仅存在于另一侧。对于这样的列,“缺失单元格”提供默认值。对于可空类型,缺省值为null,对于不可空类型(例如int),缺省值为.Net默认值0。
BY NAME
与OUTER一起使用时需要BY NAME子句。该子句指示联合是根据列名而不是位置匹配值。如果未指定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 |
+------+------+------+
The UNION (ALL) BY NAME clause can be used to combine rows from different tables by name, instead of by position. UNION BY NAME does not require both queries to have the same number of columns. Any columns that are only found in one of the queries are filled with NULL values for the other query.
SELECT * FROM capitals UNION BY NAME SELECT * FROM weather; ┌───────────┬─────────┬─────────┬────────────┐ │ city │ country │ degrees │ date │ │ varchar │ varchar │ int32 │ date │ ├───────────┼─────────┼─────────┼────────────┤ │ Amsterdam │ NULL │ 10 │ 2022-10-14 │ │ Seattle │ NULL │ 8 │ 2022-10-12 │ │ Amsterdam │ NL │ NULL │ NULL │ │ Berlin │ Germany │ NULL │ NULL │ └───────────┴─────────┴─────────┴────────────┘
NATURAL FULL JOIN
。你可以这样做:SELECT *
FROM
(SELECT *, 't1' AS source FROM t1) AS t1
NATURAL FULL JOIN
(SELECT *, 't2' AS source FROM t2) AS t2
;
如果只有一行,你可以使用join
Select t1.Col1, t1.Col2, t1.Col3, t2.Col4, t2.Col5 from Table1 t1 join Table2 t2;