我在 Postgres 中有一张名为
personal_profit
的表,如下所示:
约会 | 利润 |
---|---|
2022-09-22 | 4000 |
2022-04-25 | 5000 |
2022-01-10 | 0 |
2022-02-14 | 0 |
2022-04-12 | 2000 |
2022-05-06 | 1000 |
2022-06-13 | 0 |
我想获得按月排序的总利润,但从利润大于零的月份开始。下面的查询省略了所有不满足我条件的利润为零的记录。我只想查询从 04/2022 月份开始。
Select distinct date_trunc('month', P.date) as profit_month, SUM(P.profit) as total_profit
from personal_profit P
group by profit_month
having SUM(P.profit) > 0
order by profit_month;
约会 | 利润 |
---|---|
2022-04 | 7000 |
2022-05 | 1000 |
2022-06 | 0 |
2022-09 | 4000 |
因为您想从哪里开始,按日期排序,所以有一个非零值,您可以简单地将其添加为 where 条件:
Select distinct date_trunc('month', P.date) as profit_month, SUM(P.profit) as total_profit
from personal_profit p
where date >= (select date from personal_profit where profit >0 order by date limit 1 )
group by profit_month
order by profit_month;
条件“从利润大于零的月份开始”本质上是“从头开始跳过最长的零子序列”。这可以通过选择运行总计非零的月份或通过子查询来实现。我认为第一种方式更容易理解:
with personal_profit (date,profit) as (values
(date '2022-09-22', 4000),
(date '2022-04-25', 5000),
(date '2022-01-10', 0),
(date '2022-02-14', 0),
(date '2022-04-12', 2000),
(date '2022-05-06', 1000),
(date '2022-06-13', 0)
)
, grouped as (
select date_trunc('month', P.date) as profit_month
, sum(P.profit) as total_profit
, sum(sum(P.profit)) over (order by date_trunc('month', P.date)) as running_total
from personal_profit P
group by profit_month
)
select profit_month, total_profit
from grouped
where running_total > 0
order by profit_month;
profit_month | 总利润 |
---|---|
2022-04-01 00:00:00+01 | 7000 |
2022-05-01 00:00:00+01 | 1000 |
2022-06-01 00:00:00+01 | 0 |
2022-09-01 00:00:00+01 | 4000 |
SELECT 4
注意
running_total
表达式在理想世界中应该读作 sum(total_profit) over (order by profit_month)
,但是 Postgres 不知道同一个 select
子句中的别名(甚至 group by <alias_from_select_clause>
是 Postgres 的糖,对于其他数据库供应商来说是不寻常的)。
您可以检查第一个超过 0 的月份,并使用它来过滤所有值
Select to_char(P."date", 'YYYY-MM') as profit_month, SUM(P.profit) as total_profit
from personal_profit P
group by profit_month
having to_char(P."date", 'YYYY-MM') >= (Select
DISTINCT MIN(
to_char(P."date", 'YYYY-MM')
) over() as min_month
from personal_profit P
GROUP BY to_char(P."date", 'YYYY-MM')
having SUM(P.profit) > 0
)
order by profit_month;
profit_month | 总利润 |
---|---|
2022-04 | 7000 |
2022-05 | 1000 |
2022-06 | 0 |
2022-09 | 4000 |
SELECT 4