将SQL中的2个表与一些不同的列名组合在一起(Transact SQL)

时间:2016-10-20 15:11:51

标签: sql sql-server tsql merge union

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

我想要的是像union这样的东西,但允许使用不同的列名。

例如,

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

将合并产生:

          ID | First name | Middle Name | Surname| NI   
对于来自表2等的条目,NI的值为

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

2 个答案:

答案 0 :(得分:0)

var d  = [
    {
        name: "Roof",
        photos: [
            {image_url: "http://www.url1.com"},
            {image_url: "http://www.url2.com"},
            {image_url: "http://www.url3.com"},
       ]
    },
    {
        name: "Doors",
        photos: [
            {image_url: "http://www.url4.com"},
            {image_url: "http://www.url5.com"},
            {image_url: "http://www.url6.com"},
            {image_url: "http://www.url7.com"}
        ]
    }
];


function find(data, value){
   for(var i = 0; i < data.length; i++)
  {

      for(var j = 0; j < data[i].photos.length; i++)
      {
          if(data[i].photos[j].image_url == value)
          {
            return data[i].name;
          }
      }

  }
}

  alert(find(d,"http://www.url1.com"));

答案 1 :(得分:0)

这似乎是一个有趣的挑战,而且现在已经让我感到震惊,但如果有其他人想要尝试进一步的话,我已经走得很远了。

下面的脚本包含一个表名列表(如果需要,您可以轻松地将其扩展为包含模式和数据库),并构建所有表中所有列的列表。然后在此pivot创建一个union all脚本。

最终脚本目前分为三个部分,可以更优雅地放在一起,还包括union all中必须手动删除的尾随pivot。第一部分是每个列名称的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|