簡體   English   中英

SQL - 聯合兩個表,每個表都有幾個唯一的列

[英]SQL - union two tables, each having a few unique columns

有兩組患者記錄數據(兩張表),一組 1999-2003 年,另一組 2004-2009 年。 每個都有 >100 列; Table_A 有 ~8 個唯一列,Table_B ~ 25 個唯一列(相互比較)。 我的目標是:

  1. 包含 1999-2009 年所有數據的單個表
  2. 對於一個表中不在另一個表中的行,只需將該列的值設置為 NULL。 例如,如果表 A 有 Diagnostic_Category_12 但表 B 沒有,則該值將是表 A 中的原始值,但表 B 中的 NULL

我見過一種手動執行此操作的方法: 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 后,我建議您:

  1. 驗證您的結果並根據需要調整您的查詢。
  2. 將最終確定的 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 列? 不值得自動化。 我認為在這種情況下手動方法更快。 無論如何,有很多方法:

  1. 使用信息模式視圖或目錄視圖訪問列元數據以創建動態插入語句(聯合語句)
  2. 使用SMO(服務器管理對象)編寫程序將表合並為第三張表
  3. 將兩個表導出到 Excel,將它們合並在一起,然后將結果導入到第三個表中。

以及其他一些方式。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM