有两组患者记录数据(两个表),一组1999-2003,另一组2004-2009。每个都有> 100列; Table_A有~8个唯一列,Table_B~25个唯一列(相互比较)。我的目标是:
我见过一种手动执行此操作的方法: Unioning Two Tables With Different Number Of Columns
但是,此数据集中的列太多,无法键入每个列 - 我只想自动创建列并根据需要插入NULL值。
我正在使用SQL Server 2008R2。
答案 0 :(得分:6)
更聪明地工作,而不是更努力。
我建议你通过查询你的模式来构建一些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后,我建议您:
答案 1 :(得分:5)
即使你认为
这里有太多的专栏 数据集在
中键入每个数据
这是正确的做法。任何其他解决方案基本上都是黑客攻击。
这很容易做到,我经常使用更宽的表格(150个字段)。
在SSMS中,右键单击两个表中较大的一个,Script Table As
- > Select To
- > New Query Editor Window
。这将输出一个新窗口,其中列出了该表中每个字段的选择脚本,每个字段都在其自己的行上,因此很容易管理。
这实际上将是大约5分钟的工作。 第一次就做对了。
答案 2 :(得分:1)
快速而又脏的方法是将NULL列与其他表的唯一列的名称一起添加到每个表中。 E.g:
ALTER TABLE TableA ADD tableBUniqueColumn1 INT SPARSE NULL, tableBUniqueColumn2 INT SPARSE NULL, ...
ALTER TABLE TableB ADD tableAUniqueColumn1 INT SPARSE NULL, tableAUniqueColumn2 INT SPARSE NULL, ...
现在这些表将具有相同的架构,您可以轻松地对它们执行联合。
这是一个非常hacky的解决方法。包含SPARSE NULL列的表通常是一个警告标志,表示您不创建关系,而是尝试将所有数据放入一个表中。这通常是一个错误,会使维护数据变得更加困难。
如果您尝试规范化数据,从长远来看,创建新架构并使用现有数据填充新架构会更快,而不是破坏现有表。这可能看起来很多工作,但你只需要做一次。如果您决定采用hacky解决方法,那么您的工作将永远不会结束。
答案 3 :(得分:0)
您想要NULL
值的任何地方,您仍需要在查询中提及它们。它可能会非常难看......
您是否可以将年份用作公共列,然后将LEFT OUTER JOIN
其他两个表用于它?例如:
WITH Y AS (
SELECT 1999 YearId UNION SELECT 2000 UNION SELECT 2001 -- and so on...
)
SELECT Y.YearId, Table_A.*, Table_B.*
FROM Y LEFT OUTER JOIN
Table_A ON Y.YearId = Table_A.YearId LEFT OUTER JOIN
Table_B ON Y.YearId = Table_B.YearId
;
答案 4 :(得分:0)
超过100列?不值得自动化。在这种情况下,我认为手动方法更快。 无论如何,有很多方法:
以及其他一些方式。