没有public假期的休假如何总结?
How to summarize leave to without public holidays?
大家好(放假前)
在这种情况下,我在此 table:
添加了新的假期
+--------+---------+---------+-------------+----------+--------------------------
|ID_LEAVE|ID_WORKER| FNAME | LNAME | BEGIN_DATE | END_DATE |
+--------+---------+---------+---------+-------------+--------------------+------
| 8 | 10 | MARIO | NEED |2019-04-22 07:00:00 |2019-04-23 15:00:00 |
+--------+---------+---------+-------------+----------+--------------------------
但我知道假期是这样表示的:
我做了什么?
我做了那个查询,它汇总了按 ID_LEAVE
分组的所有员工的休假时间
SELECT leave.ID_LEAVE, leave.ID_WORKER, workers.FNAME, workers.LNAME, leave.BEGIN_DATE, leave.END_DATE,
FROM
(SELECT ADDDATE('1970-01-01', t4 * 10000 + t3 * 1000 + t2 * 100 + t1 * 10 + t0) AS date_value
FROM
(SELECT 0 t0 UNION SELECT 1 UNION SELECT 2 UNION SELECT 3 UNION SELECT 4 UNION SELECT 5 UNION SELECT 6 UNION SELECT 7 UNION SELECT 8 UNION SELECT 9) t0,
(SELECT 0 t1 UNION SELECT 1 UNION SELECT 2 UNION SELECT 3 UNION SELECT 4 UNION SELECT 5 UNION SELECT 6 UNION SELECT 7 UNION SELECT 8 UNION SELECT 9) t1,
(SELECT 0 t2 UNION SELECT 1 UNION SELECT 2 UNION SELECT 3 UNION SELECT 4 UNION SELECT 5 UNION SELECT 6 UNION SELECT 7 UNION SELECT 8 UNION SELECT 9) t2,
(SELECT 0 t3 UNION SELECT 1 UNION SELECT 2 UNION SELECT 3 UNION SELECT 4 UNION SELECT 5 UNION SELECT 6 UNION SELECT 7 UNION SELECT 8 UNION SELECT 9) t3,
(SELECT 0 t4 UNION SELECT 1 UNION SELECT 2 UNION SELECT 3 UNION SELECT 4 UNION SELECT 5 UNION SELECT 6 UNION SELECT 7 UNION SELECT 8 UNION SELECT 9) t4) calendar
INNER JOIN leave ON calendar.date_value BETWEEN DATE(leave.BEGIN_DATE) AND DATE(leave.END_DATE)
INNER JOIN workers ON leave.ID_WORKER = workers.ID_WORKER
WHERE NOT WEEKDAY(date_value) IN (5, 6)
GROUP BY ID_LEAVE;
现在我想要一个汇总所有员工休假时间但 没有假期的查询,如上图所示。 我该怎么办?我应该创建新的 "holidays" table 然后从此 table 下载该日期还是在上面的查询中添加日期?
如果你有一个日历 table 列出了所有的日子(不仅是假期,还有接下来 X 年的每一天,还有一个列是否是 public 假期等)那么你的查询看起来像
SELECT l.id_leave, count(*)
FROM calendar c INNER JOIN leave l ON c.calendar_date BETWEEN l.start_date AND l.end_date
WHERE c.day_type NOT IN ('publicholiday', 'weekend')
GROUP BY l.id_leave
您可以添加更多的复杂性,但这是核心。不确定为什么你的假期从早上 7 点开始到晚上 10 点结束,但如果你允许小数天休息,你可能想添加一些逻辑 - 将开始日期延长回午夜(这样两者之间的工作正常)然后使用一个案例根据所考虑的日期是开始日期、结束日期还是中间日期来构建分数
没有完整日历的变体 table,但有问题中的假期 table(尽管有完整的日期 - 你必须每年填充它):
SELECT L.id_leave, COUNT(*)
FROM (
SELECT '1970-01-01' + INTERVAL (seq) DAY AS date
FROM seq_0_to_24836
) C
INNER JOIN leaves L
ON C.date BETWEEN L.begin_date AND L.end_date
AND NOT WEEKDAY(date_value) IN (5, 6)
AND NOT EXISTS (
SELECT * FROM holidays H WHERE H.date = C.date
)
GROUP BY L.id_leave
注意:seq_0_to_24836 是仅限 MariaDB 的扩展,将在此处生成从纪元到 2037 年底的所有日期。
好的,在分析了所有评论和答案后,我找到了解决方案:
1) 我创建了假期 table。
2) 我创建了一个查询,它选择所有内容并汇总 leave_time,没有周末和节假日:
SELECT *,
TIME_FORMAT(SEC_TO_TIME(SUM(TIME_TO_SEC(TIMEDIFF(TIME(leave.END_DATE), TIME(leave.BEGIN_DATE))))), '%H:%i:%s') AS 'LEAVE TIME'
FROM
(SELECT ADDDATE('1970-01-01', t4 * 10000 + t3 * 1000 + t2 * 100 + t1 * 10 + t0) AS date_value FROM
(SELECT 0 t0 UNION SELECT 1 UNION SELECT 2 UNION SELECT 3 UNION SELECT 4 UNION SELECT 5 UNION SELECT 6 UNION SELECT 7 UNION SELECT 8 UNION SELECT 9) t0,
(SELECT 0 t1 UNION SELECT 1 UNION SELECT 2 UNION SELECT 3 UNION SELECT 4 UNION SELECT 5 UNION SELECT 6 UNION SELECT 7 UNION SELECT 8 UNION SELECT 9) t1,
(SELECT 0 t2 UNION SELECT 1 UNION SELECT 2 UNION SELECT 3 UNION SELECT 4 UNION SELECT 5 UNION SELECT 6 UNION SELECT 7 UNION SELECT 8 UNION SELECT 9) t2,
(SELECT 0 t3 UNION SELECT 1 UNION SELECT 2 UNION SELECT 3 UNION SELECT 4 UNION SELECT 5 UNION SELECT 6 UNION SELECT 7 UNION SELECT 8 UNION SELECT 9) t3,
(SELECT 0 t4 UNION SELECT 1 UNION SELECT 2 UNION SELECT 3 UNION SELECT 4 UNION SELECT 5 UNION SELECT 6 UNION SELECT 7 UNION SELECT 8 UNION SELECT 9) t4) calendar
INNER JOIN `leave` ON calendar.date_value BETWEEN DATE(leave.BEGIN_DATE) AND DATE(leave.END_DATE)
WHERE NOT WEEKDAY(date_value) IN (5, 6) AND NOT DATE(date_value) IN (SELECT DATE_HOLIDAY FROM holidays) GROUP BY ID_LEAVE;
我刚刚在下面的链接中进行了测试:
https://dbfiddle.uk/?rdbms=mariadb_10.3&fiddle=a25a3dc5762dba08541c002f12efc024
有人对此有任何警告吗?
非常感谢,祝你复活节愉快 ;)
大家好(放假前)
在这种情况下,我在此 table:
添加了新的假期+--------+---------+---------+-------------+----------+--------------------------
|ID_LEAVE|ID_WORKER| FNAME | LNAME | BEGIN_DATE | END_DATE |
+--------+---------+---------+---------+-------------+--------------------+------
| 8 | 10 | MARIO | NEED |2019-04-22 07:00:00 |2019-04-23 15:00:00 |
+--------+---------+---------+-------------+----------+--------------------------
但我知道假期是这样表示的:
我做了什么?
我做了那个查询,它汇总了按 ID_LEAVE
SELECT leave.ID_LEAVE, leave.ID_WORKER, workers.FNAME, workers.LNAME, leave.BEGIN_DATE, leave.END_DATE,
FROM
(SELECT ADDDATE('1970-01-01', t4 * 10000 + t3 * 1000 + t2 * 100 + t1 * 10 + t0) AS date_value
FROM
(SELECT 0 t0 UNION SELECT 1 UNION SELECT 2 UNION SELECT 3 UNION SELECT 4 UNION SELECT 5 UNION SELECT 6 UNION SELECT 7 UNION SELECT 8 UNION SELECT 9) t0,
(SELECT 0 t1 UNION SELECT 1 UNION SELECT 2 UNION SELECT 3 UNION SELECT 4 UNION SELECT 5 UNION SELECT 6 UNION SELECT 7 UNION SELECT 8 UNION SELECT 9) t1,
(SELECT 0 t2 UNION SELECT 1 UNION SELECT 2 UNION SELECT 3 UNION SELECT 4 UNION SELECT 5 UNION SELECT 6 UNION SELECT 7 UNION SELECT 8 UNION SELECT 9) t2,
(SELECT 0 t3 UNION SELECT 1 UNION SELECT 2 UNION SELECT 3 UNION SELECT 4 UNION SELECT 5 UNION SELECT 6 UNION SELECT 7 UNION SELECT 8 UNION SELECT 9) t3,
(SELECT 0 t4 UNION SELECT 1 UNION SELECT 2 UNION SELECT 3 UNION SELECT 4 UNION SELECT 5 UNION SELECT 6 UNION SELECT 7 UNION SELECT 8 UNION SELECT 9) t4) calendar
INNER JOIN leave ON calendar.date_value BETWEEN DATE(leave.BEGIN_DATE) AND DATE(leave.END_DATE)
INNER JOIN workers ON leave.ID_WORKER = workers.ID_WORKER
WHERE NOT WEEKDAY(date_value) IN (5, 6)
GROUP BY ID_LEAVE;
现在我想要一个汇总所有员工休假时间但 没有假期的查询,如上图所示。 我该怎么办?我应该创建新的 "holidays" table 然后从此 table 下载该日期还是在上面的查询中添加日期?
如果你有一个日历 table 列出了所有的日子(不仅是假期,还有接下来 X 年的每一天,还有一个列是否是 public 假期等)那么你的查询看起来像
SELECT l.id_leave, count(*)
FROM calendar c INNER JOIN leave l ON c.calendar_date BETWEEN l.start_date AND l.end_date
WHERE c.day_type NOT IN ('publicholiday', 'weekend')
GROUP BY l.id_leave
您可以添加更多的复杂性,但这是核心。不确定为什么你的假期从早上 7 点开始到晚上 10 点结束,但如果你允许小数天休息,你可能想添加一些逻辑 - 将开始日期延长回午夜(这样两者之间的工作正常)然后使用一个案例根据所考虑的日期是开始日期、结束日期还是中间日期来构建分数
没有完整日历的变体 table,但有问题中的假期 table(尽管有完整的日期 - 你必须每年填充它):
SELECT L.id_leave, COUNT(*)
FROM (
SELECT '1970-01-01' + INTERVAL (seq) DAY AS date
FROM seq_0_to_24836
) C
INNER JOIN leaves L
ON C.date BETWEEN L.begin_date AND L.end_date
AND NOT WEEKDAY(date_value) IN (5, 6)
AND NOT EXISTS (
SELECT * FROM holidays H WHERE H.date = C.date
)
GROUP BY L.id_leave
注意:seq_0_to_24836 是仅限 MariaDB 的扩展,将在此处生成从纪元到 2037 年底的所有日期。
好的,在分析了所有评论和答案后,我找到了解决方案:
1) 我创建了假期 table。
2) 我创建了一个查询,它选择所有内容并汇总 leave_time,没有周末和节假日:
SELECT *,
TIME_FORMAT(SEC_TO_TIME(SUM(TIME_TO_SEC(TIMEDIFF(TIME(leave.END_DATE), TIME(leave.BEGIN_DATE))))), '%H:%i:%s') AS 'LEAVE TIME'
FROM
(SELECT ADDDATE('1970-01-01', t4 * 10000 + t3 * 1000 + t2 * 100 + t1 * 10 + t0) AS date_value FROM
(SELECT 0 t0 UNION SELECT 1 UNION SELECT 2 UNION SELECT 3 UNION SELECT 4 UNION SELECT 5 UNION SELECT 6 UNION SELECT 7 UNION SELECT 8 UNION SELECT 9) t0,
(SELECT 0 t1 UNION SELECT 1 UNION SELECT 2 UNION SELECT 3 UNION SELECT 4 UNION SELECT 5 UNION SELECT 6 UNION SELECT 7 UNION SELECT 8 UNION SELECT 9) t1,
(SELECT 0 t2 UNION SELECT 1 UNION SELECT 2 UNION SELECT 3 UNION SELECT 4 UNION SELECT 5 UNION SELECT 6 UNION SELECT 7 UNION SELECT 8 UNION SELECT 9) t2,
(SELECT 0 t3 UNION SELECT 1 UNION SELECT 2 UNION SELECT 3 UNION SELECT 4 UNION SELECT 5 UNION SELECT 6 UNION SELECT 7 UNION SELECT 8 UNION SELECT 9) t3,
(SELECT 0 t4 UNION SELECT 1 UNION SELECT 2 UNION SELECT 3 UNION SELECT 4 UNION SELECT 5 UNION SELECT 6 UNION SELECT 7 UNION SELECT 8 UNION SELECT 9) t4) calendar
INNER JOIN `leave` ON calendar.date_value BETWEEN DATE(leave.BEGIN_DATE) AND DATE(leave.END_DATE)
WHERE NOT WEEKDAY(date_value) IN (5, 6) AND NOT DATE(date_value) IN (SELECT DATE_HOLIDAY FROM holidays) GROUP BY ID_LEAVE;
我刚刚在下面的链接中进行了测试:
https://dbfiddle.uk/?rdbms=mariadb_10.3&fiddle=a25a3dc5762dba08541c002f12efc024
有人对此有任何警告吗? 非常感谢,祝你复活节愉快 ;)