上个月第3个月的价值总和

时间:2015-02-20 18:53:10

标签: sql postgresql aggregate date-arithmetic aggregate-filter

我很难从12月份获取行数(任何来自上个月的第3个)。我试图计算在特定时间段内销售的产品数量。这是我目前的查询:

 SELECT
   a.id,
   a.default_code,
(
   SELECT SUM(product_uom_qty) 
   AS 
   "Total Sold" 
   FROM 
   sale_order_line c 
   WHERE 
   c.product_id = a.id
),
(
   SELECT SUM(product_uom_qty) 
   AS 
   "Month 3" 
   FROM sale_order_line c 
   WHERE
   c.product_id = a.id
   AND 
   MONTH(c.create_date) = MONTH(CURRENT_DATE - INTERVAL '3 Months')
   AND
   YEAR(c.create_date) = YEAR(CURRENT_DATE - INTERVAL '3 Months')
)
FROM
   product_product a 

这就是数据库的样子:

sale_order_line

product_id product_uom_qty  create_date
33         230              2014-07-01 16:47:45.294313

product_product

id  default_code 
33  WHDXEB33

这是我收到的错误:

ERROR:  function month(timestamp without time zone) does not exist
LINE 21:    MONTH(c.create_date) = MONTH(CURRENT_DATE - INTERVAL

任何帮助都指向我正确的方向?

2 个答案:

答案 0 :(得分:2)

这将避免昂贵的相关子查询

select
    pp.id, pp.default_code,
    sum(sol.product_uom_qty) as "Total Sold",
    sum((
        date_trunc('month', pp.create_date) =
        date_trunc('month', current_date) - interval '3 months'
        )::int * sol.product_uom_qty
    ) as "Month 3"
from
    product_product pp
    left join
    sale_order_line sol on pp.id = sol.product_id
group by 1, 2

booleaninteger的演员表会产生0或1,方便乘以要求的值

答案 1 :(得分:2)

使用date_trunc()计算时间戳界限:

SELECT id, default_code
    , (SELECT SUM(product_uom_qty)
        FROM   sale_order_line c 
        WHERE  c.product_id = a.id
       ) AS "Total Sold" 
    , (SELECT SUM(product_uom_qty)
        FROM   sale_order_line c 
        WHERE  c.product_id = a.id
        AND    c.create_date >= date_trunc('month', now()) - interval '2 month'
        AND    c.create_date <  date_trunc('month', now()) - interval '1 month'
      ) AS "Month 3"
FROM   product_product a;

要获得12月(现在是2月),请使用以下表达式:

    AND    c.create_date >= date_trunc('month', now()) - interval '2 month'
    AND    c.create_date <  date_trunc('month', now()) - interval '1 month'

date_trunc('month', now())收益率为“2015-02-01 00:00”,扣除2个月后,您将获得“2014-12-01 00:00”。所以,“3个月”可能是骗人的。

此外,请务必使用已证明的sargable表达式以提高性能并允许使用索引。

替代

根据您的实际数据库设计和数据分布,这可能会更快:

SELECT a.id, a.default_code, c."Total Sold", c."Month 3"
FROM   product_product a
LEFT  JOIN (
   SELECT product_id AS id
        , SUM(product_uom_qty) AS "Total Sold"
        , SUM(CASE WHEN c.create_date >= date_trunc('month', now()) - interval '2 month'
                   AND  c.create_date <  date_trunc('month', now()) - interval '1 month'
              THEN product_uom_qty ELSE 0 END) AS "Month 3" 
   FROM   sale_order_line
   GROUP  BY 1
   ) c USING (id);

由于您选择了所有行,因此这可能比相关子查询更快。在你加入之前聚合 之前加入,那就更便宜了 选择单个或少数产品时,实际上可能更慢!比较:

或使用Postgres中的FILTER子句 9.4 +

...
        , SUM(product_uom_qty) 
             FILTER (WHERE c.create_date >= date_trunc('month', now()) - interval '2 month'
                     AND   c.create_date <  date_trunc('month', now()) - interval '1 month'
                    ) AS "Month 3"
...

详细说明: