查看分为两行的单行中独立行的是/否信息

时间:2019-02-05 15:42:17

标签: mysql

我有一个表,其中包含员工的轮班数据。每行都有员工ID号,无论他们是上班还是下班,以及相应的操作日期时间。表shifts

+-----+------------+--------+---------------------+
| id  | employeeid | action | timestamp           |
+-----+------------+--------+---------------------+
| 99  | 76         | in     | 2019-01-25 12:20:43 |
| 100 | 76         | out    | 2019-01-25 22:17:22 |
| 102 | 76         | in     | 2019-01-26 10:38:14 |
| 104 | 76         | out    | 2019-01-26 17:00:26 |
| 105 | 76         | in     | 2019-01-27 11:45:35 |
| 106 | 76         | out    | 2019-01-27 14:48:27 |
| 110 | 76         | in     | 2019-01-27 17:33:15 |
| 117 | 76         | out    | 2019-01-28 02:16:21 |
+-----+------------+--------+---------------------+
  • 给定员工在同一日期可以有多个班次
  • 轮班时间可能从一天到第二天
  • action中的条目始终按inout的顺序

我需要创建一个视图,其中每个班次都表示为一行,就像这样:

+------------+---------------------+---------------------+
| employeeid | in                  | out                 |
+------------+---------------------+---------------------+
| 76         | 2019-01-25 12:20:43 | 2019-01-25 22:17:22 |
| 76         | 2019-01-26 10:38:14 | 2019-01-26 17:00:26 |
| 76         | 2019-01-27 11:45:35 | 2019-01-27 14:48:27 |
| 76         | 2019-01-27 17:33:15 | 2019-01-28 02:16:21 |
+------------+---------------------+---------------------+

如果该员工的最后一项行动是in,则出局应为NULL

我已经阅读了几篇文章,这些文章将数据从行到列进行了组合,但是找不到能处理类似二进制情况的任何东西。

有人可以为此指出正确的方向吗?谢谢。

3 个答案:

答案 0 :(得分:1)

上一个答案看起来不错,但我想知道一天要轮班两次, 或跨越几天的轮班,可能以为id很重要。

我认为id列是一个始终递增的整数主键。

我认为没有先签入就无法签出。

如果有人签入但没有签出,我假设您希望“签出”为NULL。

我认为时间戳记不是保留字,表名=移位。

尝试:

INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'blog'
]

答案 1 :(得分:1)

没有相关子查询的解决方案...

DROP TABLE IF EXISTS my_table;

CREATE TABLE my_table
(id SERIAL PRIMARY KEY
,employeeid INT NOT NULL
,action VARCHAR(12) NOT NULL
,timestamp DATETIME NOT NULL
);

INSERT INTO my_table VALUES
( 99,76,'in' ,'2019-01-25 12:20:43'),
(100,76,'out','2019-01-25 22:17:22'),
(102,76,'in' ,'2019-01-26 10:38:14'),
(104,76,'out','2019-01-26 17:00:26'),
(105,76,'in' ,'2019-01-27 11:45:35'),
(106,76,'out','2019-01-27 14:48:27'),
(110,76,'in' ,'2019-01-27 17:33:15'),
(117,76,'out','2019-01-28 02:16:21');

SELECT x.employeeid
     , x.timestamp shift_start
     , MIN(y.timestamp) shift_end 
  FROM my_table x 
  JOIN my_table y 
    ON y.employeeid = x.employeeid 
   AND y.timestamp > x.timestamp 
 WHERE x.action = 'in' 
   AND y.action = 'out' 
 GROUP 
    BY x.id;
+------------+---------------------+---------------------+
| employeeid | shift_start         | shift_end           |
+------------+---------------------+---------------------+
|         76 | 2019-01-25 12:20:43 | 2019-01-25 22:17:22 |
|         76 | 2019-01-26 10:38:14 | 2019-01-26 17:00:26 |
|         76 | 2019-01-27 11:45:35 | 2019-01-27 14:48:27 |
|         76 | 2019-01-27 17:33:15 | 2019-01-28 02:16:21 |
+------------+---------------------+---------------------+

答案 2 :(得分:0)

您可以按雇员和日期对数据进行分组,并使用带if嵌套的min和max函数获得先进先出的日期时间。

/*Example Data*/
create table if not exists EmployeWorkShift(
      id int Primary key auto_increment,
      employeid int not null,
      action  char(3) not null,
      _timestamp datetime not null
)

insert into EmployeWorkShift
value (default , 76, 'in', '2019-01-25 08:20:43')
      ,(default , 76, 'out', '2019-01-25 12:17:22')
      ,(default , 76, 'in', '2019-01-25 13:17:22')
      ,(default , 76, 'out', '2019-01-25 22:17:22')

/*sql query*/
select employeid, cast(_timestamp as date) as _Date, min(if(action = 'in', _timestamp,null)) as _in, max(if(action = 'out', _timestamp,null)) as _out
from EmployeWorkShift
group by employeid, cast(_timestamp as date)

已编辑:

我现在知道,想要的解决方案是查询为员工在办公室中的每个顺序返回一行。       因此,如果该员工从早上8点到早上12点在办公室,并在13:00再次返回并在22:00再次离开,则应该有2行。       我使用窗口函数解决了该问题,至少需要mysql版本8。如果没有mysql版本8,则可以使用自联接来解决它。

SELECT employeid, _in, _out FROM (
      SELECT employeid,action, _timestamp as _in, lead(_timestamp) over(partition by employeid order by _timestamp) as _out
      from EmployeWorkShift
) sub
where action = 'in'