给定两个这样的表:
表1
Counterparty Product Deal Date Value
foo bar Buy 01/01/24 10.00
foo bar Buy 01/01/24 10.00
foo bar Sell 01/01/24 10.00
foo bar Sell 01/01/24 10.00
fizz bar Buy 01/01/24 10.00
fizz bar Buy 01/01/24 10.00
fizz buzz Sell 01/01/24 10.00
fizz buzz Sell 01/01/24 10.00
表2
Counterparty Product Deal Date Value
foo bar Buy 01/01/24 11.00
foo bar Buy 01/01/24 09.00
foo bar Sell 01/01/24 09.00
foo bar Sell 01/01/24 10.00
fizz bar Buy 01/01/24 12.00
fizz bar Buy 01/01/24 08.00
fizz buzz Sell 01/01/24 09.00
fizz buzz Sell 01/01/24 10.00
我需要产生这样的输出:
Counterparty Bar Buzz Total col1 col2 col3 col4
foo 40 0 40 39 1 0 40
fizz 20 20 40 39 1 0 40
Total 60 20 80 78 2 0 40
哪里
col1
与 Total
相同,但源自 table2
col2
是 Total
和 col1
col3
应填写 0```col4
是 Total
和 col3
到目前为止,我可以创建动态 SQL 查询,但我不知道如何添加额外的列并执行必要的操作:
DECLARE @cols AS NVARCHAR(MAX), @colsPivot AS NVARCHAR(MAX), @query AS NVARCHAR(MAX)
-- Get Distinct Commodities
WITH cte AS (
SELECT DISTINCT Commodity
FROM Sample
)
-- Generate dynamic columns from the table
SELECT @cols = COALESCE(@cols + ', ', '') + 'ISNULL(' + QUOTENAME(Commodity) + ', 0) AS ' + QUOTENAME(Commodity),
@colsPivot = COALESCE(@colsPivot + ', ', '') + QUOTENAME(Commodity)
FROM cte
ORDER BY Commodity
-- add static columns to the pivot list:
SET @colsPivot = @colsPivot + ', [col1], [col2], [col3], [col4]'
-- Build the final query
SET @query =
'SELECT Counterparty, ' + @cols + '
FROM (
SELECT Counterparty, Commodity, SUM([Value]) AS TotalExposure
FROM Sample
GROUP BY Counterparty, Commodity
) AS pivotData
PIVOT (
SUM(TotalExposure)
FOR Commodity IN (' + @colsPivot + ') --here lies the issue
) AS pivotTable'
PRINT(@query);
输出:
Counterparty Bar Buzz
Fizz 20.00 20.00
Foo 40.00 0.00
我假设我需要将 CTE 表达式中的额外列值与将额外列与每个交易对手相匹配的表连接起来,但我很难将其可视化并创建查询。
我会采取不同的方法。首先
UNION ALL
添加源 = 1 或 2 列后的两个源。接下来,对 Counterparty
上的组合数据进行分组,并使用 条件聚合 有选择地对剩余每个结果列的值进行求和。
要添加总计行,您可以将
WITH ROLLUP
选项添加到 GROUP BY
并添加一些逻辑以有条件地将 Counterparty
列设置为 'Total'
。
SELECT
CASE WHEN GROUPING(Counterparty) = 0 THEN Counterparty ELSE 'Total' END AS Counterparty,
SUM(CASE WHEN Src = 1 AND Product = 'bar' THEN Value END) AS Bar,
SUM(CASE WHEN Src = 1 AND Product = 'buzz' THEN Value END) AS Buzz,
SUM(CASE WHEN Src = 1 THEN Value END) AS Total,
SUM(CASE WHEN Src = 2 THEN Value END) AS Col1,
SUM(CASE WHEN Src = 1 THEN Value END) - SUM(CASE WHEN Src = 2 THEN Value END) AS Col2,
0 AS Col3,
SUM(CASE WHEN Src = 1 THEN Value END) - 0 AS Col4
FROM (
SELECT *, Src = 1 FROM Table1
UNION ALL
SELECT *, Src = 2 FROM Table2
) U
GROUP BY Counterparty WITH ROLLUP
ORDER BY GROUPING(Counterparty), Counterparty
结果:
交易对手 | 酒吧 | 嗡嗡声 | 总计 | 第 1 栏 | 第 2 栏 | 第 3 栏 | 第 4 栏 |
---|---|---|---|---|---|---|---|
嘶嘶声 | 20.00 | 20.00 | 40.00 | 39.00 | 1.00 | 0 | 40.00 |
富 | 40.00 | 空 | 40.00 | 39.00 | 1.00 | 0 | 40.00 |
总计 | 60.00 | 20.00 | 80.00 | 78.00 | 2.00 | 0 | 80.00 |
如果您的产品可能不仅仅包含“bar”和“buzz”,您可以使用 dynamic SQL 来生成这些列。
请参阅 这个 SQL Fiddle 进行演示。