【问题标题】:Unioning two tables with different number of columns合并具有不同列数的两个表
【发布时间】:2023-04-03 12:59:01
【问题描述】:

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

这些有不同数量的列 - 假设表 A 有更多列。

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

【问题讨论】:

标签: sql mysql


【解决方案1】:

为具有较少列的表添加额外的列作为空

Select Col1, Col2, Col3, Col4, Col5 from Table1
Union
Select Col1, Col2, Col3, Null as Col4, Null as Col5 from Table2

【讨论】:

  • 有没有办法为 Null 列填写默认值?
  • @Hans:您可以执行类似 isnull(ColumnName, 0) as ColumnName 或 isnull(ColumnName, '-') as ColumnName 之类的操作。
  • 我意识到这个解决方案也可以工作,而不必列出所有的列。所以不用Select Col1, Col2, Col3, Null as Col4, Null as Col5 from Table2,也可以使用Select *, Null as Col4, Null as Col5 from Table2
  • 对于空值,这个 hack 对我有用:'SomeString' as DummyColumn。基本上,您只需将 NULL 替换为某个值。这在与 groupby 一起使用时也有效。
  • 任何有用的提示---比如说你想将一个 200 列的表和一个 2 列的表结合起来?
【解决方案2】:

我来到这里并遵循上述答案。但是数据类型的顺序不匹配导致了错误。下面来自另一个答案的描述会派上用场。

上面的结果和你表中的列顺序一样吗?因为 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;

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

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 等
  • note SELECT * UNION 可以被链接多次;注意 WHERE 过滤器可以在每个 SELECT 子句中使用
【解决方案3】:

对于任何额外的列,如果没有映射,则将其映射为 null,如下面的 SQL 查询

Select Col1, Col2, Col3, Col4, Col5 from Table1
Union
Select Col1, Col2, Col3, Null as Col4, Null as Col5 from Table2````

【讨论】:

    【解决方案4】:

    通常,当您使用基于集合的运算符时,您需要拥有相同数量的列,因此Kangkan's answer 是正确的。

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

    SAS(R) 9.3 SQL Procedure User's Guide

    对应(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 UNION BY NAME ON (*)

    外层

    需要 BY NAME 子句和 ON 列表。与其他集合表达式相反,OUTER UNION 的输出模式包括来自双方的匹配列和非匹配列。这会产生一种情况,即来自一侧的每一行都有“缺失的列”,这些“缺失的列”仅存在于另一侧。对于此类列,为“缺失的单元格”提供默认值。可空类型的默认值为 null,非可空类型的默认值为 .Net(例如,0 表示 int)。

    按姓名

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

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

    和代码:

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

    编辑:

    KQL支持外联合的概念:

    种类:

    inner - 结果包含所有输入表共有的列子集。

    outer - 结果包含任何输入中出现的所有列。未由输入行定义的单元格设置为 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 |
    +------+------+------+
    

    demo

    【讨论】:

    • 知道如何在 SQL 中实现这一点吗??
    • @KetanVaghasiya 据我所知,只有 SAS SQL 和 U-SQL 支持这个概念。
    【解决方案5】:

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

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

    【讨论】:

    • 两个 1 行表的并集(两个多集关系每个都有一个元组)将在结果关系中有两行(元组)。在关系代数(SQL 不是)中,联合结果可能是一行,但前提是两个输入关系包含相同的元组,例如。一元组关系的自联合。
    猜你喜欢
    • 2018-03-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-07-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多