【问题标题】:Combine 2 tables in SQL with some different column names (Transact SQL)将 SQL 中的 2 个表与一些不同的列名组合起来 (Transact SQL)
【发布时间】:2017-03-02 16:19:50
【问题描述】:

我正在尝试在 SQL Server 2012 中合并多个表,其中一些列相同,但其他列不同。我想将它们放在同一个表中,其中缺少数据的 NULL 值。

我想要的是类似联合但允许不同的列名。

例如,

Table 1:  ID | First name | Middle Name | Surname
Table 2:  ID | First name | Surname | NI

将结合产生:

          ID | First name | Middle Name | Surname| NI   

对于来自表 2 等的条目,NI 为 NULL 值

我想避免创建一个新表并插入其他表中的值,因为我的一些表有超过 100 列

【问题讨论】:

  • 您正在尝试创建一个新的物理表,或者您正在尝试进行查询以合并两个表的结果?
  • 试图创建一个新的物理表
  • 这是在您选择的文本编辑器或 Excel 中进行的简单数据操作...只需为每个表生成 select 语句并进行比较。

标签: sql sql-server tsql merge union


【解决方案1】:
 SELECT [ID], [First name], [Middle Name], [Surname], NULL as [NI]
 FROM Table1
 UNION ALL
 SELECT [ID], [First name], NULL as [Middle Name], [Surname], [NI]
 FROM Table2

【讨论】:

  • 这可行,但需要我为每个表输入所有(最多 150 个)列名
  • 脚本你的表...它会为你写出所有的列
  • 好吧 sql 只做你要求的。您必须编写查询。
【解决方案2】:

这似乎是一个有趣的挑战,并且目前已经击败了我,但如果其他人想尝试更进一步,我已经走了很远。

下面的脚本接受一个表名列表(如果需要,您可以轻松地将其扩展为包括 schema 和 db)并构建所有表中所有列的列表。然后它在pivots 上创建一个union all 脚本。

最终脚本目前分为三个部分,可以更优雅地组合在一起,其中还包括必须手动删除的 pivot 中的尾随 union all。第一部分是一个select null,用于包含每个列名,只是为了在最终输出中正确获取列标题。

这显然依赖于在所有具有相同名称的列中具有相同数据类型的所有表组合在一起,尽管即使输出的查询需要进一步的工作,它也应该尽量减少获得最终脚本所需的输入量.

查询

-- Create some dummy tables and data
create table a (a int, b int, c int, d nvarchar(500));
create table b (a int, c int, e int, f decimal(10,2));

insert into a values(1,1,1,'a');
insert into b values(2,2,2,2);


-- Create global temp tables to hold data required in the execute statement later
if object_id('tempdb..##SourceColumns') is not null
drop table ##SourceColumns;
if object_id('tempdb..##TargetColumns') is not null
drop table ##TargetColumns;


-- Find all columns in all the tables required
select t.name as TableName
        ,c.name as ColumnName
        ,ty.name as ColumnType
into ##SourceColumns
from sys.tables t
    inner join sys.columns c
        on(t.object_id = c.object_id)
    inner join sys.types ty
        on(c.system_type_id = ty.system_type_id)
where t.name in('a','b')                            -- Add list of tables here
order by t.name
        ,c.column_id;



DECLARE @ColsDummy AS NVARCHAR(MAX)
        ,@Cols AS NVARCHAR(MAX)
        ,@Query  AS NVARCHAR(MAX);


-- This is to build the start of your UNION ALL query, so that you can specify "NULL as <column name>"
set @ColsDummy = STUFF((
                    SELECT distinct ',null as ' + QUOTENAME(ColumnName)
                    FROM ##SourceColumns
                    FOR XML PATH(''), TYPE
                    ).value('.', 'NVARCHAR(MAX)') 
                ,1,1,'');

-- This is the list of column names to be used in the dynamically created PIVOT below
SET @Cols = STUFF((
                    SELECT distinct ', '','' as comma, ' + QUOTENAME(ColumnName)
                    FROM ##SourceColumns
                    FOR XML PATH(''), TYPE
                    ).value('.', 'NVARCHAR(MAX)') 
                ,1,16,'');


-- First part of final script
select 'select * from (select ''y'' as ignore, ' + @ColsDummy + ' union all';


-- Build and execute dynamic PIVOT for main part of UNION ALL query
set @Query = 'select ''select ''''n'''' as ignore,'' as [select], ' + @Cols + ', ''from '' + TableName + '' union all'' as [from]
                from 
                (
                    select TableName
                            ,ColumnName
                    from ##SourceColumns
                ) x
                pivot 
                (
                     max(ColumnName)
                    for ColumnName in (' + replace(@Cols,', '','' as comma','') + ')
                ) p
                '
execute(@Query);

-- Last part of final script
select ') a where ignore = ''n''' as [where];


-- Clean up global temp tables
if object_id('tempdb..##SourceColumns') is not null
drop table ##SourceColumns;
if object_id('tempdb..##TargetColumns') is not null
drop table ##TargetColumns;

输出

删除尾随 union all 并复制出三个 SSMS 结果窗口:

select * from (select 'y' as ignore, null as [a],null as [b],null as [c],null as [d],null as [e],null as [f] union all
select 'n' as ignore,   a   ,   b   ,   c   ,   d   ,   NULL    ,   NULL    from a union all
select 'n' as ignore,   a   ,   NULL    ,   c   ,   NULL    ,   e   ,   f   from b --<union all was here>
) a where ignore = 'n'

输出查询结果

|ignore|  a  |  b  |  c  |  d  |  e  |  f  |
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|  n   |  1  |  1  |  1  |  a  | NULL| NULL|
|  n   |  2  | NULL|  2  | NULL|  2  | 2.00|

【讨论】:

    猜你喜欢
    • 2022-01-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-01-07
    • 1970-01-01
    • 2022-01-17
    相关资源
    最近更新 更多