【问题标题】:Group by end of period instead of start date按期末而不是开始日期分组
【发布时间】:2015-12-04 20:40:27
【问题描述】:

我希望在某个数据集的结束日期之前聚合数据,而不是开始日期。例如,我想查询一个表并返回结果中显示日期的结束日期之前 30 天的匹配结果计数。原始表将仅包含进行销售的日期(时间戳)。示例:

sales_timestamp
------------------
2015-08-05 12:00:00
2015-08-06 13:00:00
2015-08-25 12:31:00
2015-08-26 01:02:00
2015-08-27 02:03:00
2015-08-29 04:23:00
2015-09-01 12:00:00
2015-09-02 12:00:00
2015-09-08 00:00:00

resulting 查询输出的示例如下:

date_period  |   count_of_sales
--------------------------------
2015-08-24   |        2
2015-08-31   |        6
2015-09-07   |        6

其中 2015-09-07 的 date_period 意味着公司在 2015 年 9 月 7 日结束的 30 天内售出了 6 件商品(如果是真正的 30 天期限,则从 2015 年 8 月 7 日开始)。

我一直在尝试date_trunc() 函数的变体,但似乎无法将截断应用于结束日期,而不是按开始时间分组。

这些数据将存放在 PostgreSQL 9.1 上。

【问题讨论】:

  • 样本数据——和一个 SQL Fiddle——真的有助于传达你想要做的事情。例如,为什么您的月经间隔一周,但您希望销售 30 天?
  • 如果您存储每周的销售数字,您的结果将不准确。 7 不能很好地进入 30。
  • @d_ominic 销售数字不是每周存储的。它们是实际销售本身的时间戳。
  • @GordonLinoff - postgresql - 我以前从未使用过 SQLfiddle,所以只存储了一些模式数据。最后,它有点毫无意义,因为它可以被认为是销售发生时记录的一个巨大的时间戳数据库。我只是想计算销售组的数量和结束日期与一些定义的提前期。
  • 所以你想检查最后一个日期叫它D....然后从D开始计算7天组直到30天?

标签: sql postgresql time-series postgresql-9.1 window-functions


【解决方案1】:

此查询满足您的所有要求:

SELECT day::date AS date_period, count_of_sales
FROM (
   SELECT *, sum(ct) OVER (ORDER BY day ROWS 30 PRECEDING) AS count_of_sales
   FROM   generate_series(date '2015-08-24' - 30  -- start 30 days earlier
                        , date '2015-09-07'
                        , interval '1 day') day
   LEFT JOIN (
      SELECT date_trunc('day', sales_timestamp) AS day, count(*)::int AS ct
      FROM   sales
      GROUP  BY 1
      ) s USING (day)
   ) sub
JOIN  generate_series(date '2015-08-24'
                    , date '2015-09-07 '
                    , interval '1 week') day USING (day);

SQL Fiddle.

说明

  1. 生成完整的相关日期集 (1st generate_series())
  2. LEFTJOIN 每天的总计数。 LEFT 保证每天 一个 行,这允许我们使用基于行数的窗口函数。
  3. sum() 用作窗口聚合函数,并带有 30 天前的自定义框架。 (你可能想用 29 代替,不清楚你是怎么数的。)

  4. 将结果连接到您希望在结果中包含的实际天数。 (第二个generate_series() 每周一天)。

请注意,如果您使用timestamptz,“日”的定义源自会话的当前时区设置。不同时区的结果可能不同。不适用于仅timestamp,不依赖于当前时区。基础知识:

带有自定义框架定义的窗口函数解释的相关答案:

【讨论】:

  • 这太棒了。谢谢你。我刚刚了解到我们将用于这个特定项目的数据库实际上是在 Vertica 上,但我会看看 generate_series 函数是否有一个近亲。
  • 不是 Vertica 用户,但 TIMESERIES Clause my.vertica.com/docs/7.1.x/HTML/index.htm#Authoring/… 可能有用。您始终可以构建自己的日历表,而不是使用 generate_series 等功能,从长远来看,实际上可能对您更容易。
猜你喜欢
  • 2023-03-09
  • 2021-09-08
  • 1970-01-01
  • 2017-01-11
  • 1970-01-01
  • 2012-04-20
  • 1970-01-01
  • 2021-07-26
  • 1970-01-01
相关资源
最近更新 更多