如何使用重置条件对列进行SUM()?

时间:2016-01-10 04:41:58

标签: sql postgresql

我正在使用Postgresql 9.2,我需要将数量从最初的100开始加总,但是如果遇到名称为X的行,我需要从此行的qty值重新启动SUM。

例如:

itemorder   name    qty
  1          A       -20
  2          A2       350
  3          X        40
  4          A        50
  5          A        -10
  6          A2       10

应该生成:

itemorder   name    qty       modifyed_sum
  1          A       -20          20       / 40 + (-20)
  2          A2       350         40       / not A
  3          X        40           40       / encounter X, restart sum with X qty.
  4          A        50          140       / 90 + 50
  5          A        -10         90        / 100 +  (-10)
  6          A2       10          100       / not A

我用这个查询来做Sum:

SELECT 100 + Sum(CASE WHEN name = 'a' THEN qty ELSE 0 END)OVER(ORDER BY itemorder DESC) as modifyed_sum,
       qty,
       name,
       itemorder
FROM   Table_Name
ORDER  BY itemorder ASC

如何将其修改为handel X案例? (可以有多个X)

2 个答案:

答案 0 :(得分:2)

您需要 RECURSIVE 查询

SQL FIDDLE DEMO

WITH RECURSIVE t("itemorder", "name", "qty", "modifyed_sum", "level") AS (
    SELECT "itemorder", 
           "name", 
           "qty", 
           100 +  CASE 
                     WHEN "name" = 'A' THEN "qty"
                     ELSE 0
                  END as "modifyed_sum",
           "itemorder" as "level"
     FROM myTable
     WHERE "itemorder" = (SELECT max("itemorder") FROM myTable)
     UNION ALL
     SELECT myTable."itemorder", 
            myTable."name", 
            myTable."qty", 
            CASE 
                WHEN myTable."name" = 'A' THEN t."modifyed_sum" + myTable."qty"
                WHEN myTable."name" = 'X' THEN myTable."qty"
                ELSE t."modifyed_sum"          
            END as "modifyed_sum",
           myTable."itemorder" as "level"
     FROM myTable 
     JOIN t
       ON myTable."itemorder" + 1 = t."itemorder" 
      AND myTable."itemorder" = t."level" - 1
     WHERE  myTable."itemorder" > 0        
)
SELECT *
FROM t
ORDER BY "itemorder"

<强>输出

| itemorder | name | qty | modifyed_sum | level |
|-----------|------|-----|--------------|-------|
|         1 |    A | -20 |           20 |     1 |
|         2 |   A2 | 350 |           40 |     2 |
|         3 |    X |  40 |           40 |     3 |
|         4 |    A |  50 |          140 |     4 |
|         5 |    A | -10 |           90 |     5 |
|         6 |   A2 |  10 |          100 |     6 |

答案 1 :(得分:0)

要根据条件重置窗口聚合,需要添加另一个级别来定义不同的行组:

with cte as
 (
   select itemorder, name, qty,
      case -- start qty for each group
         when itemorder = max(itemorder) over () then 100 -- newest row
         when name = 'X' then qty
         else 0
      end 
           -- only sum 'A' rows
      + case when name = 'A' then qty else 0 end as new_qty, 

           -- grp value increases only when name = 'X'
           -- this assigns the same value to each row in a group
           -- will be used in the next step to PARTITION BY
      sum(case when name = 'X' then 1 else 0 end) 
      over (order by itemorder desc
            rows unbounded preceding) as grp
   from myTable
 )

select itemorder, name, qty,
   sum(new_qty)
   over (partition by grp
         order by itemorder desc
         rows unbounded preceding ) as modified_sum
from cte
order by item order

请参阅fiddle

相关问题