sql - 为给定月份生成一系列周间隔

标签 sql postgresql time-series weekday generate-series

在 Postgres 9.1 数据库中,我试图为给定月份生成一系列星期,但有一些限制。我需要所有周都从星期一开始,并在另一个月开始或结束时被裁掉。

例子:

对于 2013 年 2 月,我想生成一个这样的系列:

         start
------------------------
2013-02-01 00:00:00+00
2013-02-04 00:00:00+00
2013-02-11 00:00:00+00
2013-02-18 00:00:00+00
2013-02-25 00:00:00+00

我现在的查询如下所示:

SELECT GREATEST(date_trunc('week', dates.d),
                date_trunc('month',dates.d)) as start
FROM generate_series(to_timestamp(1359676800),to_timestamp(1362095999), '1 week') as dates(d)

此查询获取前 4 周的信息,但缺少从 25 日开始的那一周。有没有可能拿到最后一周?

最佳答案

SELECT generate_series(date_trunc('week', date '2013-02-01' + interval '6 days')
                     , date_trunc('week', date '2013-02-01' + interval '1 month - 1 day')
                     , interval '1 week')::date AS day
UNION  SELECT date '2013-02-01'
ORDER  BY 1;

此变体不需要子选择、GREATESTGROUP BY,并且只生成所需的行。更简单,更快。 UNION 一行更便宜。

  • date_trunc('week', ...) 之前的月份的第一天加上 6 天,以计算 第一个星期一这个月

  • date_trunc('week', ...) 之前加 1 个月并减去 1 天以获得该月的最后一个星期一
    这可以方便地填充到单个 interval 表达式中:'1 month - 1 day'

  • UNION(不是 UNION ALL)添加它的月份的第一天,除非它已经包含在星期一。

  • 请注意,date + interval 会产生 timestamp,这是此处的最佳选择。详细解释:

自动化

您可以在 CTE 中提供日期系列的开始:

WITH t(d) AS (SELECT date '2013-02-01')  -- enter 1st of month once
SELECT generate_series(date_trunc('week', d + interval '6 days')
                     , date_trunc('week', d + interval '1 month - 1 day')
                     , interval '1 week')::date AS day
FROM   t
UNION  SELECT d FROM t
ORDER  BY 1;

或者将其封装成一个简单的SQL函数,方便重复调用:

CREATE OR REPLACE FUNCTION f_week_starts_this_month(date)
  RETURNS SETOF date AS
$func$
SELECT generate_series(date_trunc('week', $1 + interval '6 days')
                     , date_trunc('week', $1 + interval '1 month - 1 day')
                     , interval '1 week')::date AS day
UNION
SELECT $1
ORDER  BY 1
$func$  LANGUAGE sql IMMUTABLE;

调用:

SELECT * FROM f_week_starts_this_month('2013-02-01');

您可以传递该月第一天的日期,但它适用于任何 日期。第一天和下个月的所有星期一。

关于sql - 为给定月份生成一系列周间隔,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15437940/

相关文章:

sql - 相同的数据,两种不同的存储方式

ruby - 后续迁移。我的迁移文件中的 IP 地址应该是什么?

sql - Postgres中基于聚合函数查询表ID

postgresql - pg_stat_activity - 如何查看正在运行的存储过程中的当前事件

sql - 如何向已有的列添加默认值?

sql - 优化已取消订单的 SQL 查询

sql - 如何根据匹配的ID更新列

pandas - 获取 pandas 时间序列在特定时间的值

r - 在R中使用geom_rect进行时间序列着色

python - 用 matplotlib 画线(时间序列)