2017-07-07 64 views
2

我知道從長遠來看......列名相同可能是不相關的。但這裏是我得到了什麼:SQL加入兩個具有相同列名的表,並獲得每列的總和

主表:

| PersonID | 1970 | 1971 | 1972 | 1973 | 
|----------|------|------|------|------| 
|  1 | 50 | 50 | 100 | 50 | 
|  2 | 30 | 30 | 40 | 40 | 
|  3 | 40 | 40 | 40 | 20 | 

補充表

| PersonID | 1972 | 1973 | 
|----------|--------|--------| 
|  1 | 100 | (null) | 
|  2 | (null) | (null) | 
|  3 | (null) | 200 | 

我想有一個表(視圖,實際上)將加入這兩個並將列的總和加入同名的列中

組合表:

| PersonID | 1970 | 1971 | 1972 | 1973 | 
|----------|------|------|------|------| 
|  1 | 50 | 50 | 200 | 50 | 
|  2 | 30 | 30 | 40 | 40 | 
|  3 | 40 | 40 | 40 | 220 | 

生成的表格需要將兩個表格合併在一起。年份一直延續到2017年,並且每個表格都是相同的名稱。

SQLfiddle

回答

2

如果只有一個每個ID匹配行,然後left join做的:

select t1.person_id, t1.[1970], t1.[1971], 
     (t1.[1972] + coalesce(t2.[1972], 0)) as [1972], 
     (t1.[1973] + coalesce(t2.[1973], 0)) as [1973]  
from t1 left join 
    t2 
    on t1.person_id = t2.person_id 
0

除非你選擇使用動態SQL(一般情況下最好避免以防止SQL注入,漏洞,和負面的表現影響),列名相當於這裏沒有給我們任何捷徑。

的規範辦法做到這一點是明確和每一列:

SELECT mt.PersonID, COALESCE(mt.[1970], 0) + COALESCE(st.[1970], 0), COALESCE(mt.[1971], 0) + COALESCE(st.[1971], 0), ... COALESCE(mt.[2017], 0) + COALESCE(st.[2017], 0) 
FROM MasterTable mt 
LEFT JOIN SupplementalTable st 
    ON mt.PersonID = st.PersonID; 

然而,這種吸40列(這聽起來像可能在未來更多)。動態SQL通常最好避免,但有時它仍然是工作的最佳工具。這裏是你可以如何使用動態SQL解決同樣的問題:

DECLARE @dynamicSql NVARCHAR(MAX); 
DECLARE @selectList NVARCHAR(MAX); 

SELECT @selectList = COALESCE(@selectList + ', ', '') + 'COALESCE(mt.[' + mtColumns.COLUMN_NAME + '], 0)' + COALESCE(' + COALESCE(st.[' + stColumns.COLUMN_NAME + '], 0)', '') 
FROM INFORMATION_SCHEMA.COLUMNS mtColumns 
LEFT JOIN INFORMATION_SCHEMA.COLUMNS stColumns ON mtColumns.COLUMN_NAME = stColumns.COLUMN_NAME 
WHERE mtColumns.TABLE_NAME = 'MasterTable' 
     AND stColumns.TABLE_NAME = 'SupplementaryTable'; 

SET @dynamicSql = 'SELECT ' + @selectList + ' FROM MasterTable mt INNER JOIN SupplementaryTable st ON mt.PersonID = st.PersonID;'; 

EXECUTE sp_executesql @dynamicSql; 

我還沒有產生實際的表來測試,但它應該是相當接近。查詢應該爲每個字段生成一個SELECT字段總和的列表,然後運行它。它也應該跳過SupplementaryTable中不存在的字段,並且它僅適用於做的存在於MasterTable中的字段。

使用ORM(如Hibernate)可以通過提前驗證列名來減少潛在的錯誤或SQL注入漏洞。

+0

我真的想要動態SQL的工作,因爲你是對的,它確實吸引。不幸的是,當我插入我的值時,我一直得到「必須聲明標量變量@selectList」..我從來沒有玩過動態SQL,但我可以看到白天,我們正在聲明它。 – unknown6708

相關問題