将两个表汇总到时间序列中

问题描述 投票:1回答:1

假设我有两个表,这些表包含成对的时间定向数据(日期,数据)。其中一个人持有我的日常开支,另一个人持有我的日常收入。日期表示该费用/收入率何时开始。

例如:如果我在收入表中有两个记录:(2020-01-01,50),(2020-02-14,100),这意味着在2020-01-01和2020-02-14之间每天的收入为50个单位,2020-02-14之后的收入为每天100个单位。费用也一样。

我想在postgres表中生成给定时间间隔的时间序列(可能使用time generate_series(date,date,interval)函数),其中一行如下所示:(天,收入,费用)

例如,如果我的收入表如下所示:


+------------+--------+
|    date    | income |
+------------+--------+
| 2020-02-12 |     50 |
| 2020-02-14 |    100 |
+------------+--------+

以及类似费用:

+------------+--------------+
|    date    | expenses     |
+------------+--------------+
| 2020-02-12 |           70 |
| 2020-02-13 |           50 |
+------------+--------------+

我希望从2020-02-12到2020-02-15的时间间隔看起来像这样:

+------------+--------+--------------+
|    day     | income | expenses     |
+------------+--------+--------------+
| 2020-02-12 |     50 |           70 |
| 2020-02-13 |     50 |           50 |
| 2020-02-14 |    100 |           50 |
| 2020-02-15 |    100 |           50 |
+------------+--------+--------------+

因此,以后我可以例如计算我的利润,亏损和其他统计数据。我该如何实现?

sql postgresql date time-series window-functions
1个回答
0
投票

有点棘手。您可以在日期上单击full join,但是您需要填补空白。 Postgres不支持窗口函数上的ignore nulls,因此一种选择是使用条件总和来建立组,然后使用first_value()

select
    date,
    first_value(income)  over(partition by grp_i order by date) income,
    first_value(expense) over(partition by grp_e order by date) expense
from (
    select
        date, 
        i.income,
        e.expense,
        count(*) filter(where i.income  is not null) over(order by date) grp_i,
        count(*) filter(where e.expense is not null) over(order by date) grp_e
    from incomes i
    full join expenses e using(date)
) t

另一方面,您也可以从选定的日期开始(使用generate_series()),然后将表带有left join。其余逻辑保持不变:

select
    date,
    first_value(income)  over(partition by grp_i order by date) income,
    first_value(expense) over(partition by grp_e order by date) expense
from (
    select
        d.date, 
        i.income,
        e.expense,
        count(*) filter(where i.income  is not null) over(order by d.date) grp_i,
        count(*) filter(where e.expense is not null) over(order by d.date) grp_e
    from generate_series(date '2020-02-12', date '2020-02-15', interval '1' day) d(date)
    left join incomes  i on i.date = d.date
    left join expenses e on e.date = d.date
) t
order by date
© www.soinside.com 2019 - 2024. All rights reserved.