SQL连接两个具有相同列名的表,并获取每列的总和

时间:2017-07-07 21:52:43

标签: sql sql-server sql-server-2008

我知道从长远来看......列名相同可能无关紧要。但这就是我所拥有的:

主表:

| 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 个答案:

答案 0 :(得分:2)

如果每个ID只有一个匹配的行,则using namespace System; using namespace System::Windows::Forms; [STAThreadAttribute] void Main(array<String^>^ args) { Application::EnableVisualStyles(); Application::SetCompatibleTextRenderingDefault(false); MyForm form; Application::Run(%form); } 会执行此操作:

left join

答案 1 :(得分: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注入漏洞。