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

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

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

  1. | date | forecasted_units | forecasted_revenue |
  2. |---------|------------------|--------------------|
  3. | 2020-01 | 372 | 9300 |
  4. | 2020-02 | 435 | 9280 |
  5. ...

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

  1. | date | forecasted_units | forecasted_revenue |
  2. |------------|------------------|--------------------|
  3. | 2020-01-01 | 12 | 300 |
  4. | 2020-01-02 | 12 | 300 |
  5. | 2020-01-03 | 12 | 300 |
  6. ...
  7. | date | forecasted_units | forecasted_revenue |
  8. |------------|------------------|--------------------|
  9. | 2020-02-01 | 15 | 320 |
  10. | 2020-02-02 | 15 | 320 |
  11. | 2020-02-03 | 15 | 320 |
  12. ...

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

  1. | start_date | end_date | forecasted_units | forecasted_revenue |
  2. |------------|------------|------------------|--------------------|
  3. | 2020-01-01 | 2020-01-31 | 12 | 300 |
  4. | 2020-02-01 | 2020-02-29 | 15 | 320 |

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

vuv7lop3

vuv7lop31#

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

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

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

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

相关问题