sql—处理表记录中所需的重复项

nue99wik  于 2021-08-09  发布在  Java
关注(0)|答案(1)|浏览(323)

情况是这样的。我的团队以每月一次的决议来预测销售和收入数字,但希望所有的报告都以每天一次的决议来进行。所以我要做的就是接受这些数字,将每月的目标除以天数,然后保存在一个表中。所以我从这样开始:

| date    | forecasted_units | forecasted_revenue |
|---------|------------------|--------------------|
| 2020-01 | 372              | 9300               |
| 2020-02 | 435              | 9280               |
...

我的目标表现在如下所示:

| date       | forecasted_units | forecasted_revenue |
|------------|------------------|--------------------|
| 2020-01-01 | 12               | 300                |
| 2020-01-02 | 12               | 300                |
| 2020-01-03 | 12               | 300                |
...
| date       | forecasted_units | forecasted_revenue |
|------------|------------------|--------------------|
| 2020-02-01 | 15               | 320                |
| 2020-02-02 | 15               | 320                |
| 2020-02-03 | 15               | 320                |
...

现在我的table比上面的宽多了,而且都有重复的记录。正如你所看到的,有很多数据冗余。现在我的问题是,有没有更有效的方法将相同分辨率的数据保存在一个表中。
我的直接想法是重新调整表的形状,使其包含开始日期和结束日期,如下所示:

| start_date | end_date   | forecasted_units | forecasted_revenue |
|------------|------------|------------------|--------------------|
| 2020-01-01 | 2020-01-31 | 12               | 300                |
| 2020-02-01 | 2020-02-29 | 15               | 320                |

但这会将所有计算工作转移到生成所有报告的示例上,因为它必须在开始日期和结束日期之间每天生成数据。
有没有更好的办法?

vuv7lop3

vuv7lop31#

不幸的是,红移不支持方便的postgres函数 generate_series() ,这在很大程度上简化了这里的任务。
典型的替代解决方案包括一个日历表——基本上是一个列出所有可能日期的表。如果有一个具有足够行数的表,则可以使用 row_number() 以及 dateadd() :

select dateadd(day, row_number() over(order by 1) - 1, '2020-01-01') dt
from my_large_table;

您可以将结果存储在另一个表中(使用 create table ... as select ... 语法),或者直接使用查询结果。在这两种情况下,您将把它与实际的表连接起来。要计算月内的天数,我们使用窗口计数:

select
    d.dt,
    t.forecasted_unit    / count(*) over(partition by t.date) forecasted_units,
    t.forecasted_revenue / count(*) over(partition by t.date) forecasted_revenue
from (
    select dateadd(day, row_number() over(order by 1) - 1, '2020-01-01') dt
    from my_large_table
) d
inner join mytable t on t.date = date_trunc('month', d.dt)

相关问题