有两组病历数据(两张表),一组是1999-2003年,另一组是2004-2009年。每个都有 >100 列; Table_A 有 ~8 个唯一列,Table_B ~ 25 个唯一列(相互比较)。我的目标是:
- 包含 1999-2009 年所有数据的单个表
- 对于一个表中不在另一个表中的行,只需为该列设置一个 NULL 值。例如如果A表有Diagnostic_Category_12,而B表没有,则该值为A表的原始值,B表为NULL
我见过一种手动执行此操作的方法: Unioning Two Tables With Different Number Of Columns
但是,此数据集中的列太多,无法逐一输入 - 我只想自动创建列并根据需要插入 NULL 值。
我正在使用 SQL Server 2008R2。
最佳答案
更聪明地工作,而不是更努力地工作。
我建议您通过查询模式来构建一些 SQL...这样您就不会因手写而错过任何东西。您可以像这样生成脚本(只需将 @tableName1
和 @tableName2
值替换为适当的表名):
declare
@tableName1 sysname = 'myfirsttablename'
,@tableName2 sysname = 'mysecondtablename'
,@select varchar(max) = 'select';
declare @columns table
(
Id int identity(1,1)
,ColumName nvarchar(128)
,ExistsInTable1 bit
,ExistsInTable2 bit
);
-- Get a column listing with flags for their existence in each table
insert @columns
select distinct
quotename(c.Column_Name)
,iif(c2.Table_Name is null, 0, 1)
,iif(c3.Table_Name is null, 0, 1)
from Information_Schema.Columns as c
left join Information_Schema.Columns as c2
on c2.Column_Name = c.Column_Name
and c2.Table_Name = @tableName1
left join Information_Schema.Columns as c3
on c3.Column_Name = c.Column_Name
and c3.Table_Name = @tableName2
where c.Table_Name in (@tableName1, @tableName2);
-- Build the select statement for the 1sttable (using null where the column is absent)
select
@select += char(10) + iif(c.Id = 1, ' ', ',')
+ iif(c.ExistsInTable1 = 1, c.ColumName, 'null') + ' as ' + c.ColumName
from @columns as c
order by c.Id;
set @select += '
from ' + quotename(@tableName1) + '
union all
select';
-- Build the select statement for the 2ndtable (using null where the column is absent)
select
@select += char(10) + iif(c.Id = 1, ' ', ',')
+ iif(c.ExistsInTable2 = 1, c.ColumName, 'null') + ' as ' + c.ColumName
from @columns as c
order by c.Id;
set @select += '
from ' + quotename(@tableName2);
-- Print or execute your sql.
print(@select); -- or exec(@select);
生成 SQL 后,我建议您:
- 验证您的结果并根据需要调整您的查询。
- 将最终确定的 SQL 放在存储过程中,而不是为每个请求即时生成它。
关于SQL - 合并两个表,每个表都有一些唯一的列,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6601516/