[英]SQL - union two tables, each having a few unique columns
有兩組患者記錄數據(兩張表),一組 1999-2003 年,另一組 2004-2009 年。 每個都有 >100 列; Table_A 有 ~8 個唯一列,Table_B ~ 25 個唯一列(相互比較)。 我的目標是:
我見過一種手動執行此操作的方法: Unioning Two Tables With different Number of Columns
但是,此數據集中的列太多,無法輸入每一列 - 我只想自動創建列並根據需要插入 NULL 值。
我正在使用 SQL 服務器 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 后,我建議您:
即使你認為
此數據集中的列太多,無法鍵入每一列
這是正確的做法。 任何其他解決方案基本上都是黑客攻擊。
這很容易做到,而且我經常用更寬的表格(150 個字段)來做。
在 SSMS 中,右鍵單擊兩個表中較大的一個, Script Table As
-> Select To
-> New Query Editor Window
。 這將 output 到一個新的 window 一個 select 腳本列出該表中的每個字段,每個字段都將在其自己的行上,因此易於管理。
這實際上將是大約 5 分鍾的工作。 只要第一次就做對。
快速而骯臟的方法是將 NULL 列與其他表的唯一列的名稱添加到每個表中。 例如:
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 變通辦法,您的工作將永遠不會結束。
無論您想要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
;
超過 100 列? 不值得自動化。 我認為在這種情況下手動方法更快。 無論如何,有很多方法:
以及其他一些方式。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.