【问题标题】:postgresql 总列总和
【发布时间】:2022-01-23 11:25:41
【问题描述】:

选择

SELECT pp.id, TO_CHAR(pp.created_dt::date, 'dd.mm.yyyy') AS "Date", CAST(pp.created_dt AS time(0)) AS "Time",
       au.username AS "User", ss.name AS "Service", pp.amount, REPLACE(pp.status, 'SUCCESS', ' ') AS "Status",
       pp.account AS "Props", pp.external_id AS "External", COALESCE(pp.external_status, null, 'indefined') AS "External status"
  FROM payment AS pp
 INNER JOIN auth_user AS au ON au.id = pp.creator_id
 INNER JOIN services_service AS ss ON ss.id = pp.service_id
 WHERE pp.created_dt::date = (CURRENT_DATE - INTERVAL '1' day)::date
 AND ss.name = 'Some Name' AND pp.status = 'SUCCESS'


id    |    Date   |    Time   |   Service  |amount | Status |                 
------+-----------+-----------+------------+-------+--------+---
    9 | 2021.11.1 |  12:20:01 |  some serv | 100   | stat   |
   10 | 2021.12.1 |  12:20:01 |  some serv | 89    | stat   |
------+-----------+-----------+------------+-------+--------+-----        
Total |           |           |            | 189   |        |

我有一个这样的选择。我需要得到类似上面显示的东西。也就是说,我需要得到一列的总数。我已经尝试了很多东西,但对我来说没有任何效果。

【问题讨论】:

    标签: sql postgresql


    【解决方案1】:

    如果我理解正确,您想要一个结果,即在原始查询结果之后附加带有聚合值的额外行。您可以通过多种方式实现它:

    1. (推荐)最简单的方法可能是将您的原始查询与辅助查询联合起来:

    with t(id,other_column1,other_column2,amount) as (values
      (9,'some serv','stat',100),
      (10,'some serv','stat',89)
    )
    select t.id::text, t.other_column1, t.other_column2, t.amount from t
    union all
    select 'Total', null, null, sum(amount) from t
    

    2.您也可以使用group by rollup 子句,其目的正是如此。由于您的查询包含许多不涉及聚合的列,因此您的情况变得更加困难。因此,最好先计算聚合,然后再加入不重要的数据:

    with t(id,other_column1,other_column2,amount) as (values
      (9,'some serv','stat',100),
      (10,'some serv','stat',89)
    )
    select case when t.id is null then 'Total' else t.id::text end as id
         , t.other_column1
         , t.other_column2
         , case when t.id is null then ext.sum else t.amount end as amount
    from (
      select t.id, sum(amount) as sum
      from t
      group by rollup(t.id)
    ) ext
    left join t on ext.id = t.id
    order by ext.id
    

    3. 为了完整起见,我只是向您展示了应该做些什么来避免加入。在这种情况下,group by 子句必须使用除amount 之外的所有列(以保留原始行)加上聚合(以获取总和行),因此具有 2 个集合的grouping sets 子句很方便。 (rollup 子句毕竟是grouping sets 的特例。)明显的缺点是对未参与聚合的每一列重复case grouping... 表达式。

    with t(id,other_column1,other_column2,amount) as (values
      (9,'some serv','stat',100),
      (10,'some serv2','stat',89)
    )
    select case grouping(t.id) when 0 then t.id::text else 'Total' end as id
         , case grouping(t.id) when 0 then t.other_column1 end as other_column1
         , case grouping(t.id) when 0 then t.other_column2 end as other_column2
         , sum(t.amount) as amount
    from t
    group by grouping sets((t.id, t.other_column1, t.other_column2), ())
    order by t.id
    

    查看示例 (db fiddle):

    (坦率地说,除了简单的报告之外,我几乎无法想象任何其他目的,其中列将number 类型的ID 与text 类型的标签Total 混合在一起。)

    【讨论】:

    • 是的,你是对的)这是报告。谢谢你这么详细的回答!太棒了!
    猜你喜欢
    • 1970-01-01
    • 2018-05-14
    • 2021-08-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-11-10
    • 1970-01-01
    相关资源
    最近更新 更多