如何使SANDIWCH在MySql中离开查询?

问题描述 投票:-1回答:1

你们中许多人可能知道三明治休假。但是对我来说,如何在数据库级别实现它有点困难。我有一个场景,如果员工在休假之前和之后休了2个假,那么这3天都应标记为``假''。以下是我要分享的基本要求。

HERE IS REQUIREMENT OF SANDWICH LEAVE

以下是一些示例数据。我可能最终会想到用相应的期望结果来补充它。

CREATE TABLE IF NOT EXISTS `atnsystem` (
  `Emp_id` int unsigned NULL,
  `attendance_date` date NULL,
  `in_datetime` datetime NULL,
  `out_datetime` datetime NULL,
  `remark` varchar(100) NULL
) DEFAULT CHARSET=utf8;

INSERT INTO `atnsystem` (`Emp_id`, `attendance_date`, `remark`) VALUES
  ('66', '2020-02-17', 'LEAVE'),
  ('66', '2020-02-16', 'WEEK-OFF'),
  ('66', '2020-02-15', 'LEAVE');

这是SQL_FIDDLE链接table created in fiddler

我想如果备注再次像LEAVE,WEEK-OFF和LEAVE,那么WEEK-OFF也应该转换为LEAVE。

插入的内容无关紧要,但是在使用SELECT查询时,如果它发现YESTERDAY为LEAVE,而TODAY为WEEK-OFF,然后第二天又为LEAVE,则WEEK-OFF天也应被视为LEAVE。希望我能清楚地说明我的问题,我们将不胜感激。

mysql database-administration
1个回答
1
投票

一种解决方法是转换所有非休假时间,以便我们可以为每个休假时间段分配一个数字(在下面的查询中为bloc)。之后,我们可以知道每个块中的最小和最大日期,并可以在主查询中使用一个简单的子查询来确定是否在紧接最小和最大日期之前和之后的备注。例如

+--------+-----------------+-------------+--------------+----------+
| Emp_id | attendance_date | in_datetime | out_datetime | remark   |
+--------+-----------------+-------------+--------------+----------+
|     66 | 2020-02-29      | NULL        | NULL         | week-off |
|     66 | 2020-02-28      | NULL        | NULL         | NULL     |
|     66 | 2020-02-27      | NULL        | NULL         | leave    |
|     66 | 2020-02-26      | NULL        | NULL         | week-off |
|     66 | 2020-02-25      | NULL        | NULL         | week-off |
|     66 | 2020-02-24      | NULL        | NULL         | NULL     |
|     66 | 2020-02-23      | NULL        | NULL         | leave    |
|     66 | 2020-02-22      | NULL        | NULL         | week-off |
|     66 | 2020-02-21      | NULL        | NULL         | week-off |
|     66 | 2020-02-20      | NULL        | NULL         | leave    |
|     66 | 2020-02-19      | NULL        | NULL         | NULL     |
|     66 | 2020-02-18      | NULL        | NULL         | leave    |
|     66 | 2020-02-17      | NULL        | NULL         | NULL     |
|     66 | 2020-02-16      | NULL        | NULL         | WEEK-OFF |
|     66 | 2020-02-15      | NULL        | NULL         | LEAVE    |
|     66 | 2020-02-14      | NULL        | NULL         | leave    |
+--------+-----------------+-------------+--------------+----------+
16 rows in set (0.00 sec)


select t.*, b.*,
         (select t1.remark 
         from t t1
         where t1.emp_id = t.emp_id and
                t1.attendance_date < b.mindt 
         order by t1.attendance_date desc limit 1) previous_remark,
         (select t1.remark 
         from t t1
         where t1.emp_id = t.emp_id and
                t1.attendance_date > b.maxdt 
         order by t1.attendance_date asc limit 1) next_remark   ,
         case
          when 
            (select t1.remark 
            from t t1
            where t1.emp_id = t.emp_id and
                t1.attendance_date < b.mindt 
            order by t1.attendance_date desc limit 1) = 'leave'
          AND
            (select t1.remark 
            from t t1
            where t1.emp_id = t.emp_id and
                t1.attendance_date > b.maxdt 
            order by t1.attendance_date asc limit 1) ='leave' THEN
             'leave'
          ELSE t.remark 
          END as final_remark    
from t
left join
(
select a.emp_id,a.bloc,min(a.attendance_date) mindt,max(a.attendance_date) maxdt
from
(
select s.*,
        if(newremark = 'p',0,If(newremark <> @p,@b:=@b+1,@b:=@b)) bloc,
        @p:=newremark p
from
(
select t.*,
        case when remark = 'week-off' then remark else 'p' end as newremark
from t
order by attendance_date asc
) s
cross join (select@b:=0,@p:='') b
order by attendance_date asc
) a
where bloc > 0
group by a.emp_id, a.bloc
) b
on b.emp_id = t.emp_id and t.attendance_date between b.mindt and b.maxdt
order by t.emp_id,t.attendance_date;

+--------+-----------------+-------------+--------------+----------+--------+------+------------+------------+-----------------+-------------+--------------+
| Emp_id | attendance_date | in_datetime | out_datetime | remark   | emp_id | bloc | mindt      | maxdt      | previous_remark | next_remark | final_remark |
+--------+-----------------+-------------+--------------+----------+--------+------+------------+------------+-----------------+-------------+--------------+
|     66 | 2020-02-14      | NULL        | NULL         | leave    |   NULL | NULL | NULL       | NULL       | NULL            | NULL        | leave        |
|     66 | 2020-02-15      | NULL        | NULL         | LEAVE    |   NULL | NULL | NULL       | NULL       | NULL            | NULL        | LEAVE        |
|     66 | 2020-02-16      | NULL        | NULL         | WEEK-OFF |     66 | 1    | 2020-02-16 | 2020-02-16 | LEAVE           | NULL        | WEEK-OFF     |
|     66 | 2020-02-17      | NULL        | NULL         | NULL     |   NULL | NULL | NULL       | NULL       | NULL            | NULL        | NULL         |
|     66 | 2020-02-18      | NULL        | NULL         | leave    |   NULL | NULL | NULL       | NULL       | NULL            | NULL        | leave        |
|     66 | 2020-02-19      | NULL        | NULL         | NULL     |   NULL | NULL | NULL       | NULL       | NULL            | NULL        | NULL         |
|     66 | 2020-02-20      | NULL        | NULL         | leave    |   NULL | NULL | NULL       | NULL       | NULL            | NULL        | leave        |
|     66 | 2020-02-21      | NULL        | NULL         | week-off |     66 | 2    | 2020-02-21 | 2020-02-22 | leave           | leave       | leave        |
|     66 | 2020-02-22      | NULL        | NULL         | week-off |     66 | 2    | 2020-02-21 | 2020-02-22 | leave           | leave       | leave        |
|     66 | 2020-02-23      | NULL        | NULL         | leave    |   NULL | NULL | NULL       | NULL       | NULL            | NULL        | leave        |
|     66 | 2020-02-24      | NULL        | NULL         | NULL     |   NULL | NULL | NULL       | NULL       | NULL            | NULL        | NULL         |
|     66 | 2020-02-25      | NULL        | NULL         | week-off |     66 | 3    | 2020-02-25 | 2020-02-26 | NULL            | leave       | week-off     |
|     66 | 2020-02-26      | NULL        | NULL         | week-off |     66 | 3    | 2020-02-25 | 2020-02-26 | NULL            | leave       | week-off     |
|     66 | 2020-02-27      | NULL        | NULL         | leave    |   NULL | NULL | NULL       | NULL       | NULL            | NULL        | leave        |
|     66 | 2020-02-28      | NULL        | NULL         | NULL     |   NULL | NULL | NULL       | NULL       | NULL            | NULL        | NULL         |
|     66 | 2020-02-29      | NULL        | NULL         | week-off |     66 | 4    | 2020-02-29 | 2020-02-29 | NULL            | NULL        | week-off     |
+--------+-----------------+-------------+--------------+----------+--------+------+------------+------------+-----------------+-------------+--------------+
16 rows in set (0.16 sec)

t是数据库中的表名。

注意,您的数据必须是干净的,并且假设每个员工每天都有一个条目。我在输出中包含的列超出了您的要求,因此您可以查看正在发生的情况。

© www.soinside.com 2019 - 2024. All rights reserved.