为聚合列添加小计列

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() 按每个交易对手的交易价值对最终结果进行降序排序。再次感谢!

以上是关于为聚合列添加小计列的主要内容,如果未能解决你的问题,请参考以下文章

添加导致 GROUP BY 错误的聚合列

带有表达式的 s-s-rS 小计列

将分组的聚合唯一列添加到熊猫数据框

为啥我无法在 Hive 中使用具有多个插入子句的高级聚合功能?

power bi 矩阵中的自定义聚合列

SUM 值按列分组,但不能“聚合”?