前 3 个月的总和
Sum of values from 3rd previous month
我很难从 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
任何帮助我指明正确方向的帮助?
这将避免昂贵的相关子查询
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
从boolean
到integer
的转换结果为0或1,方便乘以要求和的值
使用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;
要获得十二月(现在是二月),请使用这些表达式:
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);
由于您要选择所有行,这可能比相关子查询更快。在加入时,在加入之前合计,这样更便宜。
When selecting a single or few products, this may actually be slower, though!比较:
- Aggregate a single column in query with many columns
- Optimize GROUP BY query to retrieve latest record per user
或者在 Postgres 9.4+:
中使用 FILTER
子句
...
, 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"
...
详情:
我很难从 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
任何帮助我指明正确方向的帮助?
这将避免昂贵的相关子查询
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
从boolean
到integer
的转换结果为0或1,方便乘以要求和的值
使用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;
要获得十二月(现在是二月),请使用这些表达式:
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);
由于您要选择所有行,这可能比相关子查询更快。在加入时,在加入之前合计,这样更便宜。
When selecting a single or few products, this may actually be slower, though!比较:
- Aggregate a single column in query with many columns
- Optimize GROUP BY query to retrieve latest record per user
或者在 Postgres 9.4+:
中使用FILTER
子句
...
, 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"
...
详情: