在postgresql中处理周末和节假日的最佳方式
我有一个数据库,其中包含一个sell表。此销售表包含一个带有销售日期的列。我的问题是:我只想在搜索中显示工作日 该表简化如下:在postgresql中处理周末和节假日的最佳方式,sql,postgresql,Sql,Postgresql,我有一个数据库,其中包含一个sell表。此销售表包含一个带有销售日期的列。我的问题是:我只想在搜索中显示工作日 该表简化如下: # select * from sells; id | emission ----+------------ 1 | 2019-11-19 2 | 2019-11-20 3 | 2019-11-21 4 | 2019-11-23 5 | 2019-11-24 6 | 2019-11-25 7 | 2019-11-22 (7 rows)
# select * from sells;
id | emission
----+------------
1 | 2019-11-19
2 | 2019-11-20
3 | 2019-11-21
4 | 2019-11-23
5 | 2019-11-24
6 | 2019-11-25
7 | 2019-11-22
(7 rows)
我还有一张有假期的桌子:
postgres=# select * from holidays;
id | holiday
----+------------
1 | 2019-11-20
2 | 2019-11-22
(2 rows)
CREATE TABLE holiday (holiday date, name varchar, next_workday date)
事实上,我只需要做以下工作来获得工作日:
SELECT sells.id,
EXTRACT(DOW FROM emission),
CASE WHEN EXTRACT(DOW FROM emission)=6
THEN emission+'2 days'::interval
WHEN EXTRACT(DOW FROM emission)=0
THEN emission+'1 day'::interval
WHEN holiday is not null
THEN emission+'1 day'::interval
ELSE emission
END
FROM sells
LEFT JOIN holidays ON (holiday=emission);
id | date_part | emission
----+-----------+---------------------
1 | 2 | 2019-11-19 00:00:00
2 | 3 | 2019-11-21 00:00:00
3 | 4 | 2019-11-21 00:00:00
7 | 5 | 2019-11-23 00:00:00
4 | 6 | 2019-11-25 00:00:00
5 | 0 | 2019-11-25 00:00:00
6 | 1 | 2019-11-25 00:00:00
(7 rows)
关于这种方法有两个问题:
id=7
所示CASE
语句中使用了两个表SELECT sells.id,
EXTRACT(DOW FROM COALESCE(next_workday, emission)),
CASE WHEN EXTRACT(DOW FROM COALESCE(next_workday, emission))=6
THEN emission+'2 days'::interval
WHEN EXTRACT(DOW FROM COALESCE(next_workday, emission))=0
THEN emission+'1 day'::interval
ELSE COALESCE(next_workday, emission)
END
FROM sells
LEFT JOIN holidays ON (holiday=emission);
我认为最简单的解决方案是创建一个日历表,其中包含未来10年内每天的一行。然后,您可以将每一行标记为假日或工作日(请注意,“工作日”在世界范围内从周一到周五都不是必需的),并且您可以在其中包含一列“第二天”对于每一种情况。计算10年一次并不难,甚至可以使用过程代码来完成。但是使用过程代码可以让查询变得非常简单-你只需在日期加入即可。我认为你的
更新语句需要周五(道琼斯指数=5)完成+3天,周六(道琼斯指数=6)在美国,这不是问题,除非感恩节后一天被视为公司假日。在其他国家,可能是复活节,例如丹麦,复活节是周四、周五和周一,所以从周四开始+5。
SELECT sells.id,
EXTRACT(DOW FROM COALESCE(next_workday, emission)),
CASE WHEN EXTRACT(DOW FROM COALESCE(next_workday, emission))=6
THEN emission+'2 days'::interval
WHEN EXTRACT(DOW FROM COALESCE(next_workday, emission))=0
THEN emission+'1 day'::interval
ELSE COALESCE(next_workday, emission)
END
FROM sells
LEFT JOIN holidays ON (holiday=emission);