将“前一行”值与SELECT语句中的现有行值相加

时间:2017-06-21 04:41:28

标签: postgresql select postgresql-9.3

我想将前一个值与该行中的现有值相加。

这是我的代码:

select co.partner_id, to_char(co.date, 'DD') as day, to_char(co.date, 'MM') as month, to_char(co.date, 'YYYY') as year,
       sum(col.qty * p.price) as priceday


from order_detail col
join order co on co.id=col.order_id
join product p on p.id = col.product_id

group by co.partner_id, to_char(co.date, 'MM'), to_char(co.date, 'YYYY'), to_char(co.date, 'DD')

代码变成这样:IMAGE TABLE

表格应该是这样的: IMAGES

谢谢。

2 个答案:

答案 0 :(得分:1)

以下是您需要的示例(我希望):

test=# with nums(n) as (
  select z from generate_series(1, 10) as _(z)
)
select
  n,
  sum(n) over (order by n)
from nums;
 n  | sum
----+-----
  1 |   1
  2 |   3
  3 |   6
  4 |  10
  5 |  15
  6 |  21
  7 |  28
  8 |  36
  9 |  45
 10 |  55
(10 rows)

这就是所谓的"窗口功能",请参阅此处的文档:https://www.postgresql.org/docs/current/static/tutorial-window.html

答案 1 :(得分:0)

您可以使用Window Functions with Frame子句。

如果你想与前一行进行SUM,那么你将会这样做:

SELECT o.partner_id, o.date, SUM(SUM(p.price * od.qty)) OVER (PARTITION BY o.partner_id ORDER BY o.partner_id, o.date ROWS 1 PRECEDING) AS priceday
    FROM test.order AS o
    INNER JOIN test.order_detail AS od
      ON o.id = od.order_id
    INNER JOIN test.product AS p
      ON od.product_id = p.id
    GROUP BY o.partner_id, o.date;

注意ROWS 1 PRECEDING

如果您希望与之前的所有行(运行总计)进行SUM,那么您将执行以下操作:

SELECT o.partner_id, o.date, SUM(SUM(p.price * od.qty)) OVER (PARTITION BY o.partner_id ORDER BY o.partner_id, o.date ROWS UNBOUNDED PRECEDING) AS priceday
    FROM test.order AS o
    INNER JOIN test.order_detail AS od
      ON o.id = od.order_id
    INNER JOIN test.product AS p
      ON od.product_id = p.id
    GROUP BY o.partner_id, o.date;

注意ROWS UNBOUNDED PRECEDING

<强>解释

SUM(SUM(p.price * od.qty)) OVER (PARTITION BY o.partner_id ORDER BY o.partner_id, o.date ROWS 1 PRECEDING) AS priceday是主要演员:

  • SUM(p.price * od.qty) - 计算每日价格
  • SUM(SUM(...)) OVER (...) - 多天合计多个价格
  • PARTITION BY o.partner_id - 为了将SUM保持在partner_id
  • 的边界内所必需的
  • ORDER BY o.partner_id, o.date - 按日期排序分区内的行
  • ROWS 1 PRECEDING - 为了在SUM中包含上一行以及当前行

完整示例(为了便于测试)

CREATE SCHEMA test;

CREATE TABLE test.order (
  id SERIAL PRIMARY KEY,
  partner_id int,
  date date
);

CREATE TABLE test.product (
  id SERIAL PRIMARY KEY,
  price DECIMAL
);

CREATE TABLE test.order_detail (
  id SERIAL PRIMARY KEY,
  order_id int REFERENCES test.order (id),
  product_id int REFERENCES test.product (id),
  qty int
);

INSERT INTO test.order
  (partner_id, date)
  VALUES
    (531, '2017-06-20'),
    (531, '2017-06-21'),
    (531, '2017-06-22'),
    (532, '2017-06-20'),
    (532, '2017-06-20'),
    (532, '2017-06-22'),
    (532, '2017-06-23');

INSERT INTO test.product
  (price)
  VALUES
    (1000.0);

INSERT INTO test.order_detail
  (order_id, product_id, qty)
  VALUES
    (1, 1, 300),
    (2, 1, 230),
    (3, 1, 130),
    (4, 1, 300),
    (5, 1, 230),
    (6, 1, 130),
    (7, 1, 100);

-- sum with the previous row
SELECT o.partner_id, o.date, SUM(SUM(p.price * od.qty)) OVER (PARTITION BY o.partner_id ORDER BY o.partner_id, o.date ROWS 1 PRECEDING) AS priceday
    FROM test.order AS o
    INNER JOIN test.order_detail AS od
      ON o.id = od.order_id
    INNER JOIN test.product AS p
      ON od.product_id = p.id
    GROUP BY o.partner_id, o.date;

-- sum with all the previous rows
SELECT o.partner_id, o.date, SUM(SUM(p.price * od.qty)) OVER (PARTITION BY o.partner_id ORDER BY o.partner_id, o.date ROWS UNBOUNDED PRECEDING) AS priceday
    FROM test.order AS o
    INNER JOIN test.order_detail AS od
      ON o.id = od.order_id
    INNER JOIN test.product AS p
      ON od.product_id = p.id
    GROUP BY o.partner_id, o.date;

DROP SCHEMA test CASCADE;