早上好,
我需要一个解决方案来计算特定日期之间的天数。此外,我需要排除特定日期(公众假期和周末),这很容易,并且有很多关于如何做的说明。
但我需要完成一件事。对于每个人,我也有自定义休假期,我需要从之前的结果中减去它们。
目前,我有两张桌子。一个用于自定义休假期:
+-----+----------+---------------------+---------------------+------+
| id | employee | start | end | away |
+-----+----------+---------------------+---------------------+------+
| 835 | 2.3 | 2016-12-05 00:00:00 | 2016-12-10 00:00:00 | P |
| 836 | 5.3.5.1 | 2017-01-03 00:00:00 | 2017-01-23 00:00:00 | P |
| 837 | 5.3.5.6 | 2016-12-21 00:00:00 | 2017-04-01 00:00:00 | P |
| 838 | 5.3.3.1 | 2017-01-01 00:00:00 | 2017-01-03 00:00:00 | P |
| 839 | 5.3.1.2 | 2017-01-03 00:00:00 | 2017-01-12 00:00:00 | P |
| 840 | 5.3.1.6 | 2017-01-01 00:00:00 | 2017-01-01 00:00:00 | P |
| 841 | 5.1.7 | 2017-01-09 00:00:00 | 2017-01-15 00:00:00 | P |
| 842 | 2.2 | 2017-02-16 00:00:00 | 2017-02-26 00:00:00 | P |
| 843 | 2.5 | 2017-07-31 00:00:00 | 2017-08-06 00:00:00 | P |
| 844 | 2.5 | 2017-08-21 00:00:00 | 2017-08-27 00:00:00 | P |
| 845 | 2.5 | 2017-06-26 00:00:00 | 2017-07-09 00:00:00 | P |
| 846 | 2.4 | 2017-04-04 00:00:00 | 2017-04-08 00:00:00 | P |
+-----+----------+---------------------+---------------------+------+
12 rows in set (0.00 sec)
我在开始和结束时有日期和时间的原因是该表实际上也有关于他们的工作时间表的信息。休假计划标记为“离开”列设置为“P”。
第二个表格如下:
+-----------+-------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+-----------+-------------+------+-----+---------+----------------+
| id | int(11) | NO | PRI | NULL | auto_increment |
| date | varchar(45) | YES | | NULL | |
| dayofweek | varchar(45) | YES | | NULL | |
| short | varchar(45) | YES | | NULL | |
| holiday | varchar(45) | YES | | NULL | |
+-----------+-------------+------+-----+---------+----------------+
5 rows in set (0.00 sec)
此表基本上是一个日历,其中包含有关星期几的其他信息(我知道这可以通过dayofweek()完成,但我也需要此列),“short”确定它是否是缩短的工作日(必要)计算小时数,因为一年中有几天工作日较短)和“假期”标志着公众假期。
我想弄清楚如何计算一个月(2017年8月1日 - 2017年8月31日)的工作日,减去公众假期和周末(我可以做,而且相对容易),并减去自定义假期。主要问题是,对于某些人来说,一个月内可能会有一个以上的缺席期。
如果您查看上面的示例,员工2.5的休假期从7月开始到8月结束,我只需要减去8月份该期间的金额。员工2.5在8月有另一个假期,我也需要减去这个假期。除此之外,该员工还将在6月至7月期间再度假。
完美的结果将是这样的:
+----------+-------+---------------+--------------+---------------+
| employee | month | working hours | working days | vacation days |
+----------+-------+---------------+--------------+---------------+
我能够提出的唯一解决方案是创建一个名为vacations的新表,每天都有一列,每行显示一名员工的数据。或者另一种方式是员工是列和行的日期。但在我知道没有更容易的方法之前,我不想开始玩这个想法。
再一次,我确信mysql中有一个简单的功能,但是我没弄清楚。
答案 0 :(得分:1)
要计算工作时间,请执行以下操作:
$to_time = strtotime("$row[2]");
$from_time = strtotime("$row[3]");
$diff = $to_time - $from_time
echo round(abs($diff) / 3600,2). " hour(s)";
$ row [2]& $ rows [3]是你的开始和结束日期。他们/ 3600用于计算小时数,你可以通过写60而不是3600来获得分钟。
至于工作日和假期,您可以设置一个计数器并将其递增数天,并使用$ diff变量将其减去休假。计算您喜欢的小时数或天数,然后按您喜欢的方式递增/递减。
答案 1 :(得分:0)
我整理了一下。我终于得到了我需要的东西。
起初我更改了calendar
表:
mysql> select id,date,workday from calendar where date between '2017-06-20' and '2017-06-30';
+-----+------------+---------+
| id | date | workday |
+-----+------------+---------+
| 202 | 2017-06-20 | 1 |
| 203 | 2017-06-21 | 1 |
| 204 | 2017-06-22 | 0.625 |
| 205 | 2017-06-23 | Holiday |
| 206 | 2017-06-24 | Holiday |
| 207 | 2017-06-25 | NULL |
| 208 | 2017-06-26 | 1 |
| 209 | 2017-06-27 | 1 |
| 210 | 2017-06-28 | 1 |
| 211 | 2017-06-29 | 1 |
| 212 | 2017-06-30 | 1 |
+-----+------------+---------+
11 rows in set (0.00 sec)
workday
栏中的 1表示它是普通的工作日,NULL表示不是(周末),0.625表示工作日缩短(5/8 = 0,625)。缩短的工作日为5小时。这基本上意味着如果我将workday
列加起来并乘以普通工作日的长度,我会在选定的时间段内根据法律得到正常的工作时间。
要做到这一点,目前我只是设置了一些变量,这只是一项正在进行的工作:
set @START='2016-12-01';
set @END='2016-12-31';
set @WORKDAY=8;
set @norm=(select sum(workday)*@workday from calendar where date between @start and @end);
所以变量@START
和@END
给了我感兴趣的时间段。@NORM
会给我正常的工作时间,如果一个人没有休假或病假@START
1}}和@END
。
我向schedule
添加了一些通用数据:
mysql> select id,position,start,end,away from schedule where away='P';
+-----+----------+---------------------+---------------------+------+
| id | position | start | end | away |
+-----+----------+---------------------+---------------------+------+
| 835 | 2.3 | 2016-12-05 00:00:00 | 2016-12-10 00:00:00 | P |
| 836 | 5.3.5.1 | 2017-01-03 00:00:00 | 2017-01-23 00:00:00 | P |
| 837 | 5.3.5.6 | 2016-12-21 00:00:00 | 2017-04-01 00:00:00 | P |
| 838 | 5.3.3.1 | 2017-01-01 00:00:00 | 2017-01-03 00:00:00 | P |
| 839 | 5.3.1.2 | 2017-01-03 00:00:00 | 2017-01-12 00:00:00 | P |
| 840 | 5.3.1.6 | 2017-01-01 00:00:00 | 2017-01-01 00:00:00 | P |
| 841 | 5.1.7 | 2017-01-09 00:00:00 | 2017-01-15 00:00:00 | P |
| 842 | 2.2 | 2017-02-16 00:00:00 | 2017-02-26 00:00:00 | P |
| 843 | 2.5 | 2017-07-31 00:00:00 | 2017-08-06 00:00:00 | P |
| 844 | 2.5 | 2017-08-21 00:00:00 | 2017-08-27 00:00:00 | P |
| 845 | 2.5 | 2017-06-26 00:00:00 | 2017-07-09 00:00:00 | P |
| 846 | 2.4 | 2017-04-04 00:00:00 | 2017-04-08 00:00:00 | P |
| 847 | 2.3 | 2017-07-31 00:00:00 | 2017-08-06 00:00:00 | P |
| 848 | 2.3 | 2017-08-21 00:00:00 | 2017-08-27 00:00:00 | P |
| 849 | 2.3 | 2017-06-26 00:00:00 | 2017-07-09 00:00:00 | P |
| 850 | 2.5 | 2017-08-29 00:00:00 | 2017-09-15 00:00:00 | P |
| 851 | 2.3 | 2017-08-29 00:00:00 | 2017-09-15 00:00:00 | P |
| 852 | 2.1 | 2016-11-15 00:00:00 | 2016-12-20 00:00:00 | P |
| 853 | 2.2 | 2016-11-10 00:00:00 | 2017-01-15 00:00:00 | P |
+-----+----------+---------------------+---------------------+------+
19 rows in set (0.00 sec)
为了获得有关每个员工特定工作的信息,我使用以下选择:
SELECT position,@NORM AS normhrs,@NORM - (SUM(vac_workday))*@WORKDAY AS wrkhrs
FROM
(
SELECT position,holiday_start,holiday_end,
(SELECT SUM(workday) FROM calendar WHERE date BETWEEN holiday_start AND holiday_end) AS vac_workday
FROM
(
SELECT position,
DATE_FORMAT(CASE WHEN start<=@START THEN @START ELSE start END,'%Y-%m-%d') AS 'holiday_start',
DATE_FORMAT(CASE WHEN end>=@END THEN @END ELSE end END,'%Y-%m-%d') AS 'holiday_end'
FROM schedule WHERE away IS NOT NULL AND DATE_FORMAT(CASE WHEN start<=@START AND end>=@START THEN @START
WHEN start>=@START AND start<=@END THEN start
ELSE NULL end,'%Y-%m')=DATE_FORMAT(@START,'%Y-%m')
)
AS outertable
)
AS outertable2 GROUP BY position;
给了我输出。只有人从@START
到@END
度假。如果此人不在输出中,则适用标准时间:
+----------+---------+--------+
| position | normhrs | wrkhrs |
+----------+---------+--------+
| 2.1 | 165 | 53 |
| 2.2 | 165 | 0 |
| 2.3 | 165 | 133 |
| 5.3.5.6 | 165 | 120 |
+----------+---------+--------+
4 rows in set, 6 warnings (0.00 sec)
这是我正在寻找的输出。我仍然需要提出SELECT来总结实际的工作时间,但很容易不把它放在这里。
对不起,我知道我在解释一些东西,但我是完全的菜鸟,找到了类似的,相当超级的答案,非常有帮助。