在 Db2 中的查询中排除两个时间戳之间的周末
Exclude weekend between two timestamps in a query in Db2
我有两列,每列都有时间戳
column_a column_b
2021-08-03 13:22:29 2021-08-09 15:51:59
我想计算小时差,但不包括周末(如果日期落在两个时间戳或两者之间)。
我试过 TIMESTAMPDIFF 和 HOURS_BETWEEN - 但这些仍然包括周末。
更新:
我的解决方案是......
创建一个函数来计算两天之间的天数,不包括从这里获取的周末
How to get the WORKING day diff in db2 without saturdays and sundays?
然后在我的SELECT中使用了db2s原生的DATEDIFF(8,xxx,yyy)得到总小时数,并从这个DATEDIFF中减去函数返回的值*24(小时数)
WITH
MYTAB (A, B) AS
(
VALUES ('2021-08-03 13:22:29'::TIMESTAMP, '2021-08-09 15:51:59'::TIMESTAMP)
)
, MYTAB2 (A, B) AS
(
SELECT
CASE WHEN DAYOFWEEK(A) IN (1, 7) THEN DATE (A) + 1 DAY ELSE A END
, CASE WHEN DAYOFWEEK(B) IN (1, 7) THEN B - (MIDNIGHT_SECONDS (B) + 1) SECOND ELSE B END
FROM MYTAB
)
, R (TS) AS
(
SELECT V.TS
FROM MYTAB2 T, TABLE (VALUES T.A, T.B) V (TS)
WHERE T.A <= T.B
UNION ALL
SELECT DATE (R.TS) + 1 DAY
FROM R, MYTAB2 T
WHERE DATE (R.TS) + 1 DAY < DATE (T.B)
)
SELECT
COALESCE
(
-- Seconds between start and end
(DAYS (MAX (TS)) - DAYS (MIN (TS))) * 86400
+ MIDNIGHT_SECONDS (MAX (TS)) - MIDNIGHT_SECONDS (MIN (TS))
-- SUM of seconds for weekend days is subtracted
- SUM (CASE WHEN DAYOFWEEK (TS) IN (1, 7) THEN 86400 ELSE 0 END)
, 0
) / 3600 AS HRS
FROM R
思路是先用 Recursive Common Table 表达式构造以下 table:
2021-08-03 13:22:29 --> 2021-08-04 00:00:00 (if start is a weekend)
2021-08-04 00:00:00 --> 2021-08-05 00:00:00 (if start is a weekend)
...
2021-08-08 00:00:00 --> 2021-08-07 00:00:00 (if end is a weekend)
2021-08-09 15:51:59 --> 2021-08-08 23:59:59 (if end is a weekend)
即:开始时间戳和结束时间戳之间的每一天都有一个时间戳。这些开始和结束时间戳已调整:
- 如果开始时间是周末 - 将其更改为第二天的开始时间
- 如果结束时间是周末 - 将其更改为前一天结束时间
最后的计算很简单:我们从开始和结束之间的秒数差中减去列表中所有周末的秒数总和。
我有两列,每列都有时间戳
column_a column_b
2021-08-03 13:22:29 2021-08-09 15:51:59
我想计算小时差,但不包括周末(如果日期落在两个时间戳或两者之间)。
我试过 TIMESTAMPDIFF 和 HOURS_BETWEEN - 但这些仍然包括周末。
更新: 我的解决方案是...... 创建一个函数来计算两天之间的天数,不包括从这里获取的周末 How to get the WORKING day diff in db2 without saturdays and sundays?
然后在我的SELECT中使用了db2s原生的DATEDIFF(8,xxx,yyy)得到总小时数,并从这个DATEDIFF中减去函数返回的值*24(小时数)
WITH
MYTAB (A, B) AS
(
VALUES ('2021-08-03 13:22:29'::TIMESTAMP, '2021-08-09 15:51:59'::TIMESTAMP)
)
, MYTAB2 (A, B) AS
(
SELECT
CASE WHEN DAYOFWEEK(A) IN (1, 7) THEN DATE (A) + 1 DAY ELSE A END
, CASE WHEN DAYOFWEEK(B) IN (1, 7) THEN B - (MIDNIGHT_SECONDS (B) + 1) SECOND ELSE B END
FROM MYTAB
)
, R (TS) AS
(
SELECT V.TS
FROM MYTAB2 T, TABLE (VALUES T.A, T.B) V (TS)
WHERE T.A <= T.B
UNION ALL
SELECT DATE (R.TS) + 1 DAY
FROM R, MYTAB2 T
WHERE DATE (R.TS) + 1 DAY < DATE (T.B)
)
SELECT
COALESCE
(
-- Seconds between start and end
(DAYS (MAX (TS)) - DAYS (MIN (TS))) * 86400
+ MIDNIGHT_SECONDS (MAX (TS)) - MIDNIGHT_SECONDS (MIN (TS))
-- SUM of seconds for weekend days is subtracted
- SUM (CASE WHEN DAYOFWEEK (TS) IN (1, 7) THEN 86400 ELSE 0 END)
, 0
) / 3600 AS HRS
FROM R
思路是先用 Recursive Common Table 表达式构造以下 table:
2021-08-03 13:22:29 --> 2021-08-04 00:00:00 (if start is a weekend)
2021-08-04 00:00:00 --> 2021-08-05 00:00:00 (if start is a weekend)
...
2021-08-08 00:00:00 --> 2021-08-07 00:00:00 (if end is a weekend)
2021-08-09 15:51:59 --> 2021-08-08 23:59:59 (if end is a weekend)
即:开始时间戳和结束时间戳之间的每一天都有一个时间戳。这些开始和结束时间戳已调整:
- 如果开始时间是周末 - 将其更改为第二天的开始时间
- 如果结束时间是周末 - 将其更改为前一天结束时间
最后的计算很简单:我们从开始和结束之间的秒数差中减去列表中所有周末的秒数总和。