【问题标题】:count saturdays before 15 date as working days and skip others将 15 日之前的星期六计算为工作日并跳过其他日期
【发布时间】:2022-01-26 16:15:25
【问题描述】:

我公司的政策是我们将 15 天之前的星期六算作工作日,15 天之后算作公司假期,请告诉我统计每月工作日的功能,在查询中跳过 15 天之前的所有星期日和星期六

【问题讨论】:

  • MySQL 还是 SQL Server?
  • 我们将使用其中任何一个,但更喜欢 mysql
  • @juergen d MySQL
  • 输入是什么? 2 个日期?
  • 输入是月初和同月末,即 BETWEEN '2019-07-01' AND '2019-07-31'

标签: mysql


【解决方案1】:

您可以使用以下代码根据您的要求计算工作日 -

CREATE FUNCTION FN_CNT_Working_days(StartDate DATE,
                                    EndDate   DATE) 
RETURNS INT
BEGIN
     DECLARE WORKING_DAYS INT;
     SELECT
   (DATEDIFF(EndDate, DATE(CONCAT(YEAR(EndDate), '-', MONTH(EndDate), '-', 16))) + 1)
  -(FLOOR(DATEDIFF(EndDate, DATE(CONCAT(YEAR(EndDate), '-', MONTH(EndDate), '-', 16)))/7) * 2)
  -(CASE WHEN DAYNAME(DATE(CONCAT(YEAR(EndDate), '-', MONTH(EndDate), '-', 16))) = 'Sunday' THEN 1 ELSE 0 END)
  -(CASE WHEN DAYNAME(EndDate) = 'Saturday' THEN 1 ELSE 0 END) 
   +
   (DATEDIFF(DATE(CONCAT(YEAR(EndDate), '-', MONTH(EndDate), '-', 15)), StartDate) + 1)
  -(FLOOR(DATEDIFF(DATE(CONCAT(YEAR(EndDate), '-', MONTH(EndDate), '-', 15)), StartDate)/7))
  -(CASE WHEN DAYNAME(StartDate) = 'Sunday' THEN 1 ELSE 0 END)
     INTO WORKING_DAYS;

     RETURN (WORKING_DAYS);
END;

Here 是小提琴。您还需要与此代码一起照顾假期。

【讨论】:

  • 我想从你那里再发烧一次,让它成为一个需要两个日期的函数,这样我就可以在任何地方使用它
【解决方案2】:

您可以尝试以下任一方法,也可以使用@Ankit 共享的查询。

如果你有一个像日历这样的表格,它会在很多方面很有用。

方法:1

如果您有日历表,则可以运行以下查询,

SELECT 
    SUM(CASE WHEN WEEKDAY(cal.cal_date) <> 6 AND DAY(cal.cal_date) < 16 THEN 1
             WHEN WEEKDAY(cal.cal_date) NOT IN (5, 6) AND DAY(cal.cal_date) > 15 THEN 1 END) AS 'working days'
FROM 
    calendar cal
WHERE 
    cal.cal_date BETWEEN '2019-10-01' AND '2019-10-31';

方法:2

如果创建表或视图受到限制,则可以使用以下查询生成日期范围

SELECT 
    SUM(CASE WHEN WEEKDAY(cal.cal_date) <> 6 AND DAY(cal.cal_date) < 16 THEN 1
             WHEN WEEKDAY(cal.cal_date) NOT IN (5, 6) AND DAY(cal.cal_date) > 15 THEN 1 END) AS 'working days'
FROM 
    (SELECT 
        ('1970-01-01' + INTERVAL (((((`t4`.`t4` * 10000) + (`t3`.`t3` * 1000)) + (`t2`.`t2` * 100)) + (`t1`.`t1` * 10)) + `t0`.`t0`) DAY) AS `cal_date`
    FROM
        ((((((SELECT 0 AS `t0`) UNION ALL SELECT 1 AS `1` UNION ALL SELECT 2 AS `2` UNION ALL SELECT 3 AS `3` UNION ALL SELECT 4 AS `4` UNION ALL SELECT 5 AS `5` UNION ALL SELECT 6 AS `6` UNION ALL SELECT 7 AS `7` UNION ALL SELECT 8 AS `8` UNION ALL SELECT 9 AS `9`) `t0`
        JOIN (SELECT 0 AS `t1` UNION ALL SELECT 1 AS `1` UNION ALL SELECT 2 AS `2` UNION ALL SELECT 3 AS `3` UNION ALL SELECT 4 AS `4` UNION ALL SELECT 5 AS `5` UNION ALL SELECT 6 AS `6` UNION ALL SELECT 7 AS `7` UNION ALL SELECT 8 AS `8` UNION ALL SELECT 9 AS `9`) `t1`)
        JOIN (SELECT 0 AS `t2` UNION ALL SELECT 1 AS `1` UNION ALL SELECT 2 AS `2` UNION ALL SELECT 3 AS `3` UNION ALL SELECT 4 AS `4` UNION ALL SELECT 5 AS `5` UNION ALL SELECT 6 AS `6` UNION ALL SELECT 7 AS `7` UNION ALL SELECT 8 AS `8` UNION ALL SELECT 9 AS `9`) `t2`)
        JOIN (SELECT 0 AS `t3` UNION ALL SELECT 1 AS `1` UNION ALL SELECT 2 AS `2` UNION ALL SELECT 3 AS `3` UNION ALL SELECT 4 AS `4` UNION ALL SELECT 5 AS `5` UNION ALL SELECT 6 AS `6` UNION ALL SELECT 7 AS `7` UNION ALL SELECT 8 AS `8` UNION ALL SELECT 9 AS `9`) `t3`)
        JOIN (SELECT 0 AS `t4` UNION ALL SELECT 1 AS `1` UNION ALL SELECT 2 AS `2` UNION ALL SELECT 3 AS `3` UNION ALL SELECT 4 AS `4` UNION ALL SELECT 5 AS `5` UNION ALL SELECT 6 AS `6` UNION ALL SELECT 7 AS `7` UNION ALL SELECT 8 AS `8` UNION ALL SELECT 9 AS `9`) `t4`)) AS cal
WHERE 
    cal.cal_date BETWEEN '2019-10-01' AND '2019-10-31';

小提琴here

【讨论】:

  • @ tcadidot0 @Ankit Bajpai 亲爱的我还需要的一件事是从 hr_holidays 表中的工作日也跳过公共假期,从现在到现在,所以请帮助我
  • @sarfarazahmed 如果您提出新问题而不是已经回答的旧帖子,那就太好了。
【解决方案3】:

这在没有日历表和月份的情况下有效。而且您只需要更改日期值@curdt 变量。它可以是该月内的任何日期,只要它不小于或大于实际日历日期,例如“2019-07-00”或“2019-07-32” - 这是行不通的。

#1 : Setting variable.
SET @curdt := '2019-07-01'; #only need to change the date here.
SET @startdate := LAST_DAY(@curdt-INTERVAL 1 MONTH)+INTERVAL 1 DAY;
SET @lastdate := LAST_DAY(@curdt);

#2 : Count workdays. 

SELECT  SUM(CASE WHEN DAY(dt) <= 15 AND WEEKDAY(dt)=6 THEN 0
            WHEN DAY(dt) > 15 AND WEEKDAY(dt) IN (5,6) THEN 0
            ELSE 1 END) AS Workdays 
FROM
(SELECT dt 
 FROM   (
         #custom calendar
         SELECT CONCAT_WS('-',curmy,CONCAT(n2,n1)) dt 
         FROM
                (SELECT 0 AS n1 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 ) a CROSS JOIN
                (SELECT 0 n2 UNION 
                 SELECT 1 UNION 
                 SELECT 2 UNION 
                 SELECT 3) b CROSS JOIN
                (SELECT LEFT(@curdt,7) curmy) c
          ) zz
 WHERE  dt BETWEEN @startdate AND @lastdate) XX
 GROUP BY MONTH(dt);

刚刚尝试了一个新查询,可能只是在此处添加以供将来参考:

SET @curdate := CURDATE()-INTERVAL 1 MONTH;

SELECT * FROM
(SELECT CONCAT_WS('-',df,CONCAT(b,c)) dm FROM 
(SELECT DATE_FORMAT(@curdate, '%Y-%m') df) a CROSS JOIN
(SELECT 0 b UNION SELECT 1 b UNION SELECT 2 UNION SELECT 3) b CROSS JOIN
(SELECT 0 c 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) c) d WHERE DAY(dm) BETWEEN 1 AND DAY(LAST_DAY(dm))
ORDER BY dm;

此方法适用于 MariaDB - 使用它的序列引擎: From MariaDB 10.1, the Sequence engine is installed by default.

SELECT DATE_FORMAT(CONCAT_WS('-',a.seq,b.seq,c.seq), '%Y-%m-%d') dates
   FROM seq_2020_to_2021 a -- year range
   CROSS JOIN seq_1_to_12 b -- month range
   CROSS JOIN seq_1_to_31 c  -- day range
HAVING dates IS NOT NULL; -- excluding invalid dates returned as NULL 

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-03-30
    • 1970-01-01
    • 2022-12-11
    • 1970-01-01
    • 2022-12-29
    • 1970-01-01
    • 2021-04-24
    相关资源
    最近更新 更多