【问题标题】:Sum the “previous row” value with existing row value in a SELECT statement将“前一行”值与 SELECT 语句中的现有行值相加
【发布时间】:2017-11-23 19:42:34
【问题描述】:

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

这是我的代码:

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')

代码变成这样:

表格应该是这样的:

谢谢。

【问题讨论】:

    标签: postgresql select postgresql-9.3


    【解决方案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

    【讨论】:

      【解决方案2】:

      您可以使用带有 Frame 子句的窗口函数。

      如果你想与上一行求和,那么你会这样做:

      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

      如果你想对所有前面的行求和(运行总计),那么你会这样做:

      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;
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2021-04-10
        • 2011-10-15
        • 1970-01-01
        • 1970-01-01
        • 2016-05-27
        • 1970-01-01
        • 2010-10-17
        • 1970-01-01
        相关资源
        最近更新 更多