两个日期之间的周数

时间:2018-09-18 11:51:38

标签: sql postgresql

我正在尝试将两个日期转换为一系列记录。日期之间的每周记录。

另外,如果范围在周中开始或结束,则应使用原始的开始和结束日期来裁剪星期。我还假设一周从星期一开始。

开始日期为: 2018年9月5日,结束日期为 2018年9月27日。我想检索以下结果:

| # | Start Date   | End date     |
|---------------------------------|
| 0 | '05/09/2018' | '09/09/2018' |
| 1 | '10/09/2018' | '16/09/2018' |
| 2 | '17/09/2018' | '23/09/2018' |
| 3 | '24/09/2018' | '27/09/2018' |

我已经取得了一些进步-目前,我可以通过以下方式获得日期范围之间的总周数:

SELECT (
  EXTRACT(
      days FROM (
                  date_trunc('week', to_date('27/09/2018', 'DD/MM/YYYY')) -
                  date_trunc('week', to_date('05/09/2018', 'DD/MM/YYYY'))
                ) / 7
  ) + 1
) as total_weeks;

对于上述SQL,总周数将返回4。这是我遇到的问题,从整数到实际结果集。

3 个答案:

答案 0 :(得分:1)

使用generate_series()

select gs.*
from generate_series(date_trunc('week', '2018-09-05'::date),
                     '2018-09-27'::date,
                     interval '1 week'
                    ) gs(dte)

答案 1 :(得分:1)

窗口功能是您的朋友:

SELECT week_num,
       min(d) AS start_date,
       max(d) AS end_date
FROM (SELECT d,
             count(*) FILTER (WHERE new_week) OVER (ORDER BY d) AS week_num
      FROM (SELECT DATE '2018-09-05' + i AS d,
                   extract(dow FROM DATE '2018-09-05'
                                    + lag(i) OVER (ORDER BY i)
                          ) = 1 AS new_week
            FROM generate_series(0, DATE '2018-09-27' - DATE '2018-09-05') AS i
           ) AS week_days
     ) AS weeks
GROUP BY week_num
ORDER BY week_num;

 week_num | start_date |  end_date  
----------+------------+------------
        0 | 2018-09-05 | 2018-09-09
        1 | 2018-09-10 | 2018-09-16
        2 | 2018-09-17 | 2018-09-23
        3 | 2018-09-24 | 2018-09-27
(4 rows)

答案 2 :(得分:0)

最终我扩展了Gordon的解决方案,以达到以下目的,但是Laurenz的答案稍微简洁一些。

select
  (
    case when (week_start - interval '6 days' <= date_trunc('week', '2018-09-05'::date)) then '2018-09-05'::date else week_start end
  ) as start_date,
  (
    case when (week_start + interval '6 days' >= '2018-09-27'::date) then '2018-09-27'::date else week_start + interval '6 days' end
  ) as end_date
from generate_series(
         date_trunc('week', '2018-09-05'::date),
         '2018-09-27'::date,
          interval '1 week'
      ) gs(week_start);