【问题标题】:Advice needed for populating historical postgresql table with multiple rows per date time每个日期时间用多行填充历史 postgresql 表所需的建议
【发布时间】:2021-11-03 11:26:18
【问题描述】:

我有一个 SQL 查询,它每小时生成多行,其中包含市场信息(每个市场一行),例如当时从如下所示的表中累积的唯一客户数,然后是查询:

organization_id transaction_id transaction_date_time market
6789 80031 2021-06-07 15:33 3
6789 80032 2021-06-07 15:34 3
6789 80033 2021-06-07 15:44 3
6789 80034 2021-06-07 15:45 3
1234 80035 2021-06-17 14:07 1
1234 80036 2021-06-17 14:07 1
4321 80037 2021-07-05 11:51 2
4321 80038 2021-07-05 11:51 2
1234 80039 2021-07-13 15:41 1
1234 80040 2021-07-14 09:41 1
1234 80041 2021-07-14 09:55 1
    select
        date_trunc('hour', current_timestamp) as "date_time"
        ,ct.country_code as market
        ,count(distinct ct.organization_id) acc_alltime_organizations
        ,count(distinct case when ct.transaction_date_time >= current_date - interval '30' day then ct.organization_id else null end) acc_1m_organizations
    from customer_transactions ct
    group by
            "date_time"
            ,market

上面是我为 current_timestamp 创建的表示例(实际上有更多的累积,但不应该大幅改变设置)。我希望这些行不仅适用于当前时间戳,而且适用于每个小时,例如 2016-01-01 10:00:00 直到现在。这意味着,例如,我想知道在 2018-09-09 00:00:00 上,有 10000 个组织曾经使用过该产品,并且在该日期的前一个月有 1000 个独特的组织使用过该产品。

可以按如下方式生成包含我需要这些行的所有时间的列:

select count(*)
from generate_series(
    (select date_trunc('hour', min(ct.transaction_date_time))
                from customer_transactions ct 
    ),
    current_date,
    interval '1 hour'
) as t("date_time")
)

想要的结果如下表所示:

date_time Market acc_alltime_organizations acc_1m_organizations
2016-01-01 10:00 1 10 5
2016-01-01 10:00 2 9 4
2016-01-01 10:00 3 8 3
2016-01-01 10:00 4 7 2
2016-01-01 11:00 1 10 5
2016-01-01 11:00 2 9 4
2016-01-01 11:00 3 8 3
2016-01-01 11:00 4 7 2
2016-01-01 12:00 1 11 6
2016-01-01 12:00 2 10 5
2016-01-01 12:00 3 9 4
2016-01-01 12:00 4 8 3

所以我的想法是循环使用上面的代码 sn-p 生成的小时数,并将第一个代码 sn-p 中的 current_date 替换为可以循环通过的日期变量,然后将每个市场每小时行,但我不知道如何实施。

如果有另一种方法比循环更受欢迎,那么也请告诉我:)。非常感谢您的帮助!

【问题讨论】:

  • 。 . .请提供样本数据和期望的结果。您的第一个查询在语法上不正确(我认为它只是缺少group by,但不清楚还有什么可能缺少)。
  • 您说得对,我从原始查询中删除了太多内容,我会确保将其改正。我还将尽可能多地添加一些示例数据:)。

标签: sql postgresql date insert


【解决方案1】:

如果这是您的原始查询:

select date_trunc('hour', current_timestamp) as date_time,
       ct.country_code as market,
       count(distinct ct.organization_id) as acc_alltime_organizations,
       count(distinct case when ct.transaction_date_time >= current_date - interval '30' day then ct.organization_id end) as acc_1m_organizations
from customer_transactions ct
group by ct.country_code;

然后您可以使用以下方法修改小时范围:

select h.date_time,
       t.country_code as market,
       count(distinct ct.organization_id) as acc_alltime_organizations,
       count(distinct case when ct.transaction_date_time >= h.date_time - interval '30' day then ct.organization_id end) as acc_1m_organizations
from (select generate_series(min(ct.transaction_date_time), current_date, interval '1 hour') as date_time
      from customer_transactions ct
     ) h left join
     customer_transactions ct
     on ct.transaction_date_time <= h.date_time
group by h.date_time, ct.country_code

可能有更有效的方法来计算您想要的,但这回答了您提出的问题。您可能想提出一个问题,其中包含示例数据、所需结果以及对所需逻辑的清晰解释。

【讨论】:

  • 感谢您的回答。我添加了有关我拥有的数据集样本和所需结果的更多信息。我尝试运行您的脚本,不幸的是它需要很长时间才能运行,即使我只在数据集的较小开发样本上运行了过去 3 小时(超过 500 秒并且还在计数)。如果您能够为更有效的解决方案提供一些指示,那就太好了。我不介意逻辑,只要我(有点)有效地得到结果。谢谢!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-11-20
  • 2021-11-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多