【问题标题】:start date & end date from table in generate_series()generate_series() 中表的开始日期和结束日期
【发布时间】:2018-11-03 05:50:20
【问题描述】:

我正在尝试计算 PostgreSQL 中某个日期范围之间的工作日。

SELECT 
     SUM(CASE WHEN extract (dow FROM foo) IN(1,2,3,4,5) THEN 1 ELSE 0 
END) 
FROM (SELECT ('2007-04-01'::date + 
(generate_series(0,'2007-04-30'::date 
 - '2007-04-01'::date)||'days')::interval) AS foo) foo

我想用start_dateend_date 替换名为myTable 的表中的日期 start_dateend_date 格式为 yyyy-mm-dd

实际上我需要它来显示每一行的工作日日期差异

|start_date |end_date |
------------------------
|2018-04-01 |2018-04-30| 
|2018-05-01 |2018-05-30| 

这是我的代码:

  SELECT pto.start_date, pto.end_date, 
  SUM(CASE WHEN extract (dow FROM foo) IN(1,2,3,4,5) THEN 1 ELSE 0 END) as theDIFF 
  FROM (
  SELECT start_date, (start_date::date + 
  (generate_series(0,end_date::date 
    - start_date::date)||'days')::interval) AS foo
  FROM pto
  ) foo inner join pto pto
  on pto.start_date = foo.start_date 
  group by pto.start_date, pto.end_date

我的输出:

  |start_date(date)| end_date(date) |theDiff(integer)
  ---------------------------------------------------
  |2017-06-01      |  2017-06-01    |        29     |
  |2017-05-29      |  2017-06-02    |        12     |
  ---------------------------------------------------

预期输出:

  |start_date(date)| end_date(date) |theDiff(integer)
  ---------------------------------------------------
  |2017-06-01      |  2017-06-01    |        1      |
  |2017-05-29      |  2017-06-02    |        5      |
  ---------------------------------------------------

【问题讨论】:

  • 你想从表格的哪一行取值?
  • 所示语句无效,因为您需要为group by 提供sum() - 该表中还有其他列吗?什么是主键?
  • @a_horse_with_no_name 解决了我的错误,但我的计算搞砸了。对于 2017-06-01 - 2017-06-01 ,我得到 29。
  • 您真的应该向我们展示完整的表结构和您期望的结果。
  • @a_horse_with_no_name 我添加了表结构和输出。

标签: sql postgresql generate-series


【解决方案1】:

您的示例代码有点混乱,因此仅考虑工作日和您的表格,这将给出预期的输出:

CREATE TABLE myTable (start_date date, end_date date);

INSERT INTO myTable VALUES('2017-06-01', '2017-06-01'),('2017-05-29', '2017-06-02');

SELECT start_date, end_date,
       SUM(CASE WHEN EXTRACT(dow FROM days) BETWEEN 1 AND 5 THEN 1 ELSE 0 END)
  FROM myTable
 CROSS JOIN LATERAL generate_series(start_date, end_date, interval '1 day') AS days
 GROUP BY start_date, end_date;

它将生成行,每行都有 start_date、end_date 和它们之间的一天。然后它将按 start_date、end_date 和 SUM() 日期聚合,日期在 1 到 5 之间(周一至周五)。

没有聚合它看起来像这样:

 start_date |  end_date  |          days          | dow
------------+------------+------------------------+-----
 2017-06-01 | 2017-06-01 | 2017-06-01 00:00:00+02 |   4
 2017-05-29 | 2017-06-02 | 2017-05-29 00:00:00+02 |   1
 2017-05-29 | 2017-06-02 | 2017-05-30 00:00:00+02 |   2
 2017-05-29 | 2017-06-02 | 2017-05-31 00:00:00+02 |   3
 2017-05-29 | 2017-06-02 | 2017-06-01 00:00:00+02 |   4
 2017-05-29 | 2017-06-02 | 2017-06-02 00:00:00+02 |   5

分组方式:

 start_date |  end_date  | sum
------------+------------+-----
 2017-06-01 | 2017-06-01 |   1
 2017-05-29 | 2017-06-02 |   5

【讨论】:

    猜你喜欢
    • 2012-08-19
    • 1970-01-01
    • 2022-01-23
    • 2015-04-07
    • 1970-01-01
    • 1970-01-01
    • 2020-10-05
    • 2019-12-10
    • 2021-11-12
    相关资源
    最近更新 更多