我有一个表,其中包含员工的轮班数据。每行都有员工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
中的条目始终按in
,out
的顺序我需要创建一个视图,其中每个班次都表示为一行,就像这样:
+------------+---------------------+---------------------+
| 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
我已经阅读了几篇文章,这些文章将数据从行到列进行了组合,但是找不到能处理类似二进制情况的任何东西。
有人可以为此指出正确的方向吗?谢谢。
答案 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'