【问题标题】:Get the sum of values per date while obtaining recent value per date?在获取每个日期的最近值的同时获取每个日期的值总和?
【发布时间】:2021-11-04 19:13:48
【问题描述】:

我有一个表格,动作,显示用户使用他们的卡。 是这样的:

movementdate expense deposit balance
2021-07-09 19:23:49 0 2 2
2021-07-09 20:40:13 0 6 8
2021-07-09 13:50:01 0 2 10
2021-07-10 11:50:31 5 0 5
2021-07-10 12:59:15 0 5 10
2021-07-10 18:01:39 10 0 0

它显示了他们的存款和费用,还显示了他们的最终余额。 我有这个查询,可以获取每天的存款和费用总额;

select EXTRACT(day FROM m.movementdate) as d, EXTRACT(month FROM m.movementdate) as m, 
       EXTRACT(year FROM m.movementdate) as y, sum(m.expense) as TotalExpense, 
       sum (m.deposit) as TotalDeposit
from movements m 
group by 3,2,1

但我还想获得他们每天余额的最后记录。

类似这样的:

Date TotalExpense TotalDeposit Balance
2021-07-09 0 10 10
2021-07-10 15 5 0

我怎样才能得到最后一部分?我找到了一些方法来获取当天的最后一个余额,但我不知道如何将它包含在同一个查询中。

【问题讨论】:

    标签: sql postgresql date


    【解决方案1】:

    另一种达到预期效果的方法是使用窗口函数row_number()

    这里是db<>fiddle

    with cte as
    (
      select 
        movementdate::date as dt,
        EXTRACT(day FROM movementdate) as d,
        EXTRACT(month FROM movementdate) as m, 
        EXTRACT(year FROM movementdate) as y,
        sum(expense) over (partition by movementdate::date) as expense,
        sum(deposit) over (partition by movementdate::date) as deposit,
        balance,
        row_number() over (partition by movementdate::date order by movementdate desc) as rn
      from movements
    )
    
    select 
      dt,
      d, 
      m, 
      y, 
      expense, 
      deposit, 
      balance
    from cte
    where rn = 1
    order by
      1, 2, 3
    

    输出:

    *-------------------------------------------------------*
    |  dt          d    m   y     expense   deposit  balance|
    *-------------------------------------------------------*
    | 2021-07-09    9   7   2021    0         10       8    |
    | 2021-07-10    10  7   2021    15         5       0    |
    *-------------------------------------------------------*
    

    【讨论】:

    • 这太棒了!非常感谢!
    【解决方案2】:

    一种方法使用数组:

    select EXTRACT(day FROM m.movementdate) as d,
           EXTRACT(month FROM m.movementdate) as m, 
           EXTRACT(year FROM m.movementdate) as y,
           sum(m.expense) as TotalExpense, 
           sum (m.deposit) as TotalDeposit,
           (array_agg(m.balance order by m.movementdate desc))[1] as balance
    from movements m 
    group by 3,2,1;
    

    我还建议您使用m.movementdate::date 而不是定义前三列。

    【讨论】:

      【解决方案3】:
      另一种选择是使用PostgreSQL LATERAL Subquery

      类似:

      WITH movements_per_day AS (
        select m.movementdate::date AS dt
           , EXTRACT(day FROM m.movementdate) as d
           , EXTRACT(month FROM m.movementdate) as m
           , EXTRACT(year FROM m.movementdate) as y
           , sum(m.expense) as TotalExpense
           , sum (m.deposit) as TotalDeposit
        from movements m
        group by 1,2,3,4
      )
      SELECT movements_per_day.*, last_movement.balance
        FROM movements_per_day
        CROSS JOIN LATERAL (
          SELECT movements.balance
          FROM movements
          WHERE movements.movement_date::date = movements_per_day.dt
          ORDER BY movements.movementdate DESC 
          LIMIT 1
        ) AS last_movement
      

      正如其他答案所暗示的,使用m.movementdate::date 而不是前三列会更简单一些。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2020-12-22
        • 2020-02-12
        • 2019-12-10
        • 1970-01-01
        • 1970-01-01
        • 2017-03-07
        相关资源
        最近更新 更多