mysql 计算不包括星期六和星期日的事件天数的总和

s5a0g9ez  于 2023-02-15  发布在  Mysql
关注(0)|答案(1)|浏览(128)

我需要一个查询来计算给定ITMaven从当前年份开始的所有“假期”类型的天数,不包括周末,假期可能持续几天或一天。如果假期持续几天,则假期的开始是开始,假期的结束是结束,如果假期是一天,则开始和结束具有相同的日期
目前我已经把假期加起来了,它验证假期是一天还是几天
我需要从假期天数总和中排除周末
表:kal_termin

id,start,end,id_typ

表格:卡尔乌切斯尼克

id,id_termin,id_informatyk

我的疑问

SELECT  kal_uczestnik.id_informatyk, SUM(
    CASE 
        WHEN start = end THEN 1
        ELSE DATEDIFF(end, start) + 1
    END
) as days_off 
FROM kal_termin,kal_uczestnik
WHERE kal_termin.id=kal_uczestnik.id_termin AND kal_uczestnik.id_informatyk = 119 AND kal_termin.id_typ = 1 AND YEAR(start) = YEAR(CURRENT_DATE) 
GROUP BY  kal_uczestnik.id_informatyk;
oaxa6hgo

oaxa6hgo1#

您需要使用日历表或递归公用表表达式(CTE)来构建日历,如下例所示:

WITH RECURSIVE `calendar` (`date`, `is_weekend`) AS (
    SELECT
        MAKEDATE(YEAR(CURRENT_DATE), 1), -- first day of current year
        DAYOFWEEK(MAKEDATE(YEAR(CURRENT_DATE), 1)) IN (1, 7) -- is day Sat or Sun
    UNION ALL
    SELECT
        `date` + INTERVAL 1 DAY,
        DAYOFWEEK(`date` + INTERVAL 1 DAY) IN (1, 7)
    FROM `calendar`
    WHERE `date` + INTERVAL 1 DAY < MAKEDATE(YEAR(CURRENT_DATE) + 1, 1) -- first day of next year
)
SELECT  `u`.`id_informatyk`, COUNT(`c`.`date`) AS `days_off`
FROM `kal_termin` `t`
JOIN `kal_uczestnik` `u`
    ON `t`.`id` = `u`.`id_termin`
    AND `u`.`id_informatyk` = 119
    AND `t`.`id_typ` = 1
JOIN `calendar` `c`
    ON `c`.`date` BETWEEN `t`.`start` AND `t`.`end`
    AND `c`.`is_weekend` = 0
GROUP BY  u.id_informatyk;

calendar CTE构建一个当前年份中所有日期的列表,沿着是否每天is_weekend。然后,我们根据calendar.date是否介于startend之间,将该列表连接到现有查询。仅包括is_weekend = 0的日期。这假定startend都包括在休息日中。如果不是这种情况,您可以更改联接标准。
感谢@shanmukhavangaru标记this question。我不知道这个方法。不幸的是,接受的答案对于这个问题和引用的问题都有错误的矩阵,因为它不包括结束日期。There is an answer在提供正确字符串的页面上。
如果要使用建议的解决方案,则正确的矩阵(包括起始日期和终止日期)为:

| M T W T F S S
-|--------------
M| 1 2 3 4 5 5 5
T| 5 1 2 3 4 4 4
W| 4 5 1 2 3 3 3
T| 3 4 5 1 2 2 2
F| 2 3 4 5 1 1 1
S| 1 2 3 4 5 0 0
S| 1 2 3 4 5 5 0

并且,连接字符串为:

1234555512344445123333451222234511112345001234550

因此,给定现有查询,解决方案将是:

SELECT
    u.id_informatyk,
    SUM(
        5 * (DATEDIFF(t.end, t.start) DIV 7) + MID('1234555512344445123333451222234511112345001234550', 7 * WEEKDAY(t.start) + WEEKDAY(t.end) + 1, 1)
    ) as days_off 
FROM kal_termin t
JOIN kal_uczestnik u
    ON t.id = u.id_termin AND u.id_informatyk = 119
WHERE t.id_typ = 1
AND t.start >= MAKEDATE(YEAR(CURRENT_DATE), 1) -- start of current year
AND t.start < MAKEDATE(YEAR(CURRENT_DATE) + 1, 1) -- start of next year
GROUP BY  u.id_informatyk;

相关问题