为聚合列添加小计列
Posted
技术标签:
【中文标题】为聚合列添加小计列【英文标题】:Add a subtotal column for aggregated columns 【发布时间】:2020-11-13 14:47:18 【问题描述】:这是我的交易、交易者和交易对手数据集:
TRADER_ID | TRADER_NAME | EXEC_BROKER | TRADE_AMOUNT | TRADE_ID
ABC123 | Jules Winnfield | GOLD | 10000 | ASDADAD
XDA241 | Jimmie Dimmick | GOLD | 12000 | ASSVASD
ADC123 | Vincent Vega | BARC | 10000 | ZXCZCX
ABC123 | Jules Winnfield | BARC | 15000 | ASSXCQA
ADC123 | Vincent Vega | CRED | 250000 | RFAQQA
ABC123 | Jules Winnfield | CRED | 5000 | ASDQ23A
ABC123 | Jules Winnfield | GOLD | 5000 | AVBDQ3A
我希望生成一份可重复的月度报告,让我可以查看在交易对手(EXEC_BROKER 字段)级别汇总的交易活动,并带有小计 - 如下所示:
TRADER_ID | TRADER_NAME | NO._OF_CCP_USED | CCP | TRADED_AMT_WITH_CCP | VALUE_OF_TOTAL_TRADES | TRADES_WITH_CCP | TOTAL_TRADES
ABC123 | Jules Winnfield | 3 | GOLD | 15000 | 35000 | 2 | 4
ABC123 | Jules Winnfield | 3 | BARC | 15000 | 35000 | 1 | 4
ABC123 | Jules Winnfield | 3 | CRED | 5000 | 35000 | 1 | 4
...以此类推。
这个想法是汇总每个交易对手的交易数量(我已经使用计数函数完成了),以及使用 ccp 的交易金额总和,但我很难获得每个交易对手旁边的“小计”字段交易者,如上面我想要的输出所示 - 所以你可以在这里看到 Jules 总共与 3 个交易对手打交道,他们之间有 4 笔交易,总金额为 35000。
我尝试过使用聚合和 over by 函数的组合,但无济于事。
SELECT
OT.TRADER_ID,
OT.TRADER_NAME,
OT.EXEC_BROKER,
SUM(OT.TRADE_AMOUNT) AS VALUE_OF_TOTAL_TRADES,
COUNT(OT.TRADE_ID) AS TOTAL_TRADES,
COUNT(OT.EXEC_BROKER) OVER PARTITION BY (OT.TRADER_ID) AS NO._OF_CCP_USED,
SUM(OT.TRADE_AMOUNT) OVER PARTITION BY (OT.EXEC_BROKER) AS TRADED_AMT_WITH_CCP,
COUNT(OT.TRADE_ID) OVER PARTITION BY (OT.EXEC_BROKER) AS TRADES_WITH_CCP
FROM dbo.ORDERS_TRADES OT
GROUP BY OT.TRADER_ID, OT.TRADER_NAME, OT.EXEC_BROKER, OT.TRADE_AMOUNT, OT.TRADE_ID
上面的代码运行但返回数百万行。当我按行删除分区时,我得到的结果减去我正在寻找的小计列。
有什么建议吗?非常感谢!
编辑:
为我提供了所需输出的最终代码:更新我的问题以提供此响应(感谢 Gordon Linoff),以便其他人受益:
SELECT
OT.TRADER_ID,
OT.TRADER_NAME,
OT.EXEC_BROKER,
RANK() OVER (PARTITION BY OT.TRADER_ID ORDER BY
SUM(OT.TRADE_AMOUNT) DESC) AS CCP_RANK,
SUM(OT.TRADE_AMOUNT) AS TRADED_AMT_WITH_CCP,
SUM(SUM(OT.TRADE_AMOUNT)) OVER (PARTITION BY OT.TRADER_ID) AS
VALUE_OF_TOTAL_TRADES,
COUNT(*) OVER (PARTITION BY OT.TRADER_ID) AS NUM_OF_CCP_USED,
SUM(COUNT(OT.TRADE_ID)) OVER (PARTITION BY OT.TRADER_ID) AS
TOTAL_TRADES
FROM dbo.ORDERS_TRADES OT
GROUP BY OT.TRADER_ID, OT.TRADER_NAME, OT.EXEC_BROKER
【问题讨论】:
这个问题很难理解,因为你一直在转换术语。例如,您谈论“交易对手”,但没有“交易对手”列。您谈论“小计”,但没有“小计”列。您的查询是指“trade_amount”,但没有“trade_amount”列。您的查询引用了“exec_broker”,但没有“exec_broker”列。 嗨 - 道歉显然不是故意的。 CCP = 交易对手,也称为 EXEC_BROKER。实际上,我从未使用过“小计”术语。我认为这是在编辑我的标题时发生的。我所指的“小计”是上面我想要的输出中的 TRADES_WITH_CCP 和 TOTAL_TRADES。 TRADE_AMOUNT 与 TRADED_AMT 相同,但我已经在我的问题中解决了这个问题以澄清。谢谢! 【参考方案1】:对命名法做一些假设,这是一个不使用任何花哨的解决方案,因此很容易维护,尽管它不是最有效的:
create table trades
(
TRADER_ID varchar(10),
TRADER_NAME varchar(20),
CCP char(4),
TRADED_AMT decimal(10,2),
TRADE_ID varchar(10) primary key
);
insert trades
values
('ABC123', 'Jules Winnfield', 'GOLD', 10000 , 'ASDADAD'),
('XDA241', 'Jimmie Dimmick ', 'GOLD', 12000 , 'ASSVASD'),
('ADC123', 'Vincent Vega ', 'BARC', 10000 , 'ZXCZCX'),
('ABC123', 'Jules Winnfield', 'BARC', 15000 , 'ASSXCQA'),
('ADC123', 'Vincent Vega ', 'CRED', 250000, 'RFAQQA'),
('ABC123', 'Jules Winnfield', 'CRED', 5000 , 'ASDQ23A'),
('ABC123', 'Jules Winnfield', 'GOLD', 5000 , 'AVBDQ3A');
with trader_totals as
(
select trader_id,
distinct_ccps = count(distinct CCP),
total_amt = sum(traded_amt),
total_count = count(*)
from trades
group by trader_id
)
select trader_id = tr.trader_id,
trader_name = trader_name,
distinct_CCP_count = tt.distinct_ccps,
CCP = tr.CCP,
this_CCP_traded_amt = sum(traded_amt),
total_traded_amt = tt.total_amt,
this_CCP_traded_count = count(*),
total_traded_count = tt.total_count
from trades tr
join trader_totals tt on tt.trader_id = tr.trader_id
group by tr.trader_id,
tr.trader_name,
tr.CCP,
tt.distinct_ccps,
tt.total_amt,
tt.total_count
【讨论】:
【参考方案2】:你似乎想要:
SELECT OT.TRADER_ID, OT.TRADER_NAME, OT.CCP,
COUNT(*) OVER (PARTITION BY OT.TRADER_ID) as NUM_CCP,
SUM(OT.TRADED_AMT) AS TRADED_AMT_WITH_CCP,
SUM(SUM(OT.TRADED_AMT)) OVER (PARTITION BY OT.TRADER_ID) AS VALUE_OF_TOTAL_TRADES,
COUNT(OT.TRADE_ID) AS CCP_TRADES,
SUM(COUNT(OT.TRADE_ID)) OVER (PARTITION BY OT.TRADER_ID) AS TOTAL_TRADES
FROM ORDERS_TRADES OT
GROUP BY OT.TRADER_ID, OT.TRADER_NAME, OT.CCP;
我不确定您的查询与您想要的结果有什么关系。这些列与您的要求无关。
Here 是一个 dbfiddle。
【讨论】:
您的代码非常完美,我能够对其进行调整以解决我的问题 - 非常感谢!我还使用 RANK() 按每个交易对手的交易价值对最终结果进行降序排序。再次感谢!以上是关于为聚合列添加小计列的主要内容,如果未能解决你的问题,请参考以下文章