【问题标题】:How to conditional sum two columns in PostgreSQL 9.3如何在 PostgreSQL 9.3 中对两列进行条件求和
【发布时间】:2017-01-15 12:40:37
【问题描述】:

我有如下数据表:

month      marketid   totalsold   totalshipped   lefttoship_thismonth
....
01-01-2015   1          100            50              50
01-01-2015   2          10             3               7
01-01-2015   3          0              0               0
01-02-2015   1          0              50             -50
01-02-2015   2          20             0               20
01-02-2015   3          0              0                0 

基本上,此表显示每个市场每月的订单和发货信息。 month 列中的日期01-01-2015 实际上代表Jan 2015(整月)。

我想SUM lefttoship_thismonth 每个市场的每个月与所有前几个月。这是必要的,因为有人可以在一月份下订单,而二月份就提供了。所以我想知道我每月还需要运送多少件物品。

输出应该是:

month      marketid   totalsold   totalshipped   totallefttoship   TOTALLEFT
01-01-2015   1          100            50              50             50   
01-01-2015   2          10             3               7               7
01-01-2015   3          0              0               0              0
01-02-2015   1          0              50             -50             0    /50-50
01-02-2015   2          20             0               20             27  /7+20
01-02-2015   3          0              0                0               0  / 0+0

我该怎么做? 我不知道如何以这种方式求和,month 列很难使用。

【问题讨论】:

    标签: sql postgresql


    【解决方案1】:

    如果您的 PostgreSQL 版本(还)不允许窗口函数,您可以使用子查询来完成):

    WITH t (month, marketid, totalsold, totalshipped, lefttoship_thismonth) AS
    (VALUES
        ('01-01-2015'::date,   1, 100, 50,  50),
        ('01-01-2015'::date,   2,  10,  3,   7),
        ('01-01-2015'::date,   3,   0,  0,   0),
        ('01-02-2015'::date,   1,   0, 50, -50),
        ('01-02-2015'::date,   2,  20,  0,  20),
        ('01-02-2015'::date,   3,   0,  0,   0) 
    )
    
    SELECT
        month, 
        marketid, 
        totalsold, 
        totalshipped, 
        lefttoship_thismonth, 
        (SELECT sum(lefttoship_thismonth) 
           FROM t t2 
          WHERE t2.marketid  = t1.marketid AND
                t2.month    <= t1.month
        ) AS total_left
    FROM 
        t t1
    ORDER BY
        month, marketid ;
    

    会得到以下结果:

    |------------+----------+-----------+--------------+----------------------+------------|
    |   month    | marketid | totalsold | totalshipped | lefttoship_thismonth | total_left |
    |------------+----------+-----------+--------------+----------------------+------------|
    | 2015-01-01 |    1     |    100    |      50      |          50          |     50     |
    |------------+----------+-----------+--------------+----------------------+------------|
    | 2015-01-01 |    2     |    10     |      3       |          7           |     7      |
    |------------+----------+-----------+--------------+----------------------+------------|
    | 2015-01-01 |    3     |     0     |      0       |          0           |     0      |
    |------------+----------+-----------+--------------+----------------------+------------|
    | 2015-01-02 |    1     |     0     |      50      |         -50          |     0      |
    |------------+----------+-----------+--------------+----------------------+------------|
    | 2015-01-02 |    2     |    20     |      0       |          20          |     27     |
    |------------+----------+-----------+--------------+----------------------+------------|
    | 2015-01-02 |    3     |     0     |      0       |          0           |     0      |
    |------------+----------+-----------+--------------+----------------------+------------|
    

    如果你可以使用Window函数(效率更高),你可以这样做:

    SELECT
        month, 
        marketid, 
        totalsold, 
        totalshipped, 
        lefttoship_thismonth, 
        ( sum(lefttoship_thismonth) 
               OVER (PARTITION BY marketid ORDER BY month ROWS UNBOUNDED PRECEDING)
        ) AS total_left
    FROM 
        t t1
    ORDER BY
        month, marketid ;
    

    如果您的 month 列是 varchar(不是一个好主意),您可以将其强制转换为 date,或使用 to_date 函数。

    【讨论】:

      【解决方案2】:

      Sum()Over()窗口聚合函数

      SELECT "month",
             marketid,
             totalsold,
             totalshipped,
             lefttoship_thismonth,
             Sum(lefttoship_thismonth)OVER(partition BY marketid ORDER BY month ) AS TOTALLEFT
      FROM   yourtable
      ORDER  BY "month",
                marketid 
      

      【讨论】:

      • 稍微打败我。 :) +1
      • @avi 您的month 列的类型是什么?
      • @avi - 也添加了演示。正如 Gurv 询问 Month 列的数据类型是什么
      • 如果是varchar,可以试试to_date(month,'dd-mm-yyyy')而不是order by中的month
      • @avi - 也添加了演示。看看它给出了预期的结果
      【解决方案3】:

      评论太长了。

      如果该列是 varchar 类型,那么您必须将其转换为日期才能在 order by 子句中使用它。

      select t.*,
        sum(totallefttoship) over 
         (partition by marketid order by to_date(month,'dd-mm-yyyy')) as TOTALLEFT
      From yourtable t
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2015-03-25
        • 2020-07-26
        • 2021-07-04
        • 1970-01-01
        • 1970-01-01
        • 2016-10-23
        • 2018-12-28
        • 2021-01-26
        相关资源
        最近更新 更多