如果有3个或更多条件查询MySQL
感谢您看到我关于是否有3个或更多条件查询MySQL的问题 在我从评论中了解更多信息后,我开始研究并改进我的问题,几天后我从下面的回答栏中更正了它,结果是这样的,我的问题有了一个新的案例,希望你能帮助我解决这个问题 从HrAttLogs表中查询: 我们可以看到状态字段包含0和1,其中0表示进入,1表示退出 在我掌握的数据中:如果有3个或更多条件查询MySQL,mysql,sql,Mysql,Sql,感谢您看到我关于是否有3个或更多条件查询MySQL的问题 在我从评论中了解更多信息后,我开始研究并改进我的问题,几天后我从下面的回答栏中更正了它,结果是这样的,我的问题有了一个新的案例,希望你能帮助我解决这个问题 从HrAttLogs表中查询: 我们可以看到状态字段包含0和1,其中0表示进入,1表示退出 在我掌握的数据中: | FingerId | ShiftId | DateIn | DateOut | ScanIn | ScanOut | WorkhourIn | Wor
| FingerId | ShiftId | DateIn | DateOut | ScanIn | ScanOut | WorkhourIn | WorkhourOut | TIME_IN | TIME_OUT | ShiftIn_1 | ShiftIn_2 | ShiftIn_3 | ShiftOut_1 | ShiftOut_2 | ShiftOut_3 | WorkhourIn_2 | WorkhourIn_3 | WorkhourOut_2 | WorkhourOut_3 |
| -------- | ------- | ---------- | ---------- | -------- | -------- | ---------- | ----------- | --------- | -------- | --------- | --------- | --------- | ---------- | ---------- | ---------- | ------------ | ------------ | ------------- | ------------- |
| 2 | 10 | 2020-01-03 | 2020-01-03 | 07:20:13 | 14:05:00 | 07:00:00 | 14:00:00 | 00:20:13 | 00:05:00 | 05:00:00 | 12:00:00 | 19:00:00 | 12:00:00 | 19:00:00 | 05:00:00 | 14:00:00 | 21:00:00 | 21:00:00 | 07:00:00 |
| 2 | 10 | 2020-01-06 | 2020-01-06 | 17:22:18 | | 14:00:00 | 21:00:00 | 03:22:18 | | 05:00:00 | 12:00:00 | 19:00:00 | 12:00:00 | 19:00:00 | 05:00:00 | 14:00:00 | 21:00:00 | 21:00:00 | 07:00:00 |
| 2 | 10 | 2020-01-07 | 2020-01-07 | 16:21:30 | 21:51:57 | 14:00:00 | 21:00:00 | 02:21:30 | 00:51:57 | 05:00:00 | 12:00:00 | 19:00:00 | 12:00:00 | 19:00:00 | 05:00:00 | 14:00:00 | 21:00:00 | 21:00:00 | 07:00:00 |
| 2 | 10 | 2020-01-08 | 2020-01-08 | 06:56:55 | | 07:00:00 | 14:00:00 | -00:03:05 | | 05:00:00 | 12:00:00 | 19:00:00 | 12:00:00 | 19:00:00 | 05:00:00 | 14:00:00 | 21:00:00 | 21:00:00 | 07:00:00 |
| 2 | 10 | 2020-01-09 | 2020-01-09 | 21:10:00 | | 21:00:00 | 21:00:00 | 00:10:00 | | 05:00:00 | 12:00:00 | 19:00:00 | 12:00:00 | 19:00:00 | 05:00:00 | 14:00:00 | 21:00:00 | 21:00:00 | 07:00:00 |
在第5行数据中,DateIn显示日期2020-01-09,ScanIn在21:00:00自动DateOut显示日期后一天,其中2020-01-10可以在HrAttLogs查询中看到,ScanOut应在04:05:05显示。我怎么得到它?我一直在寻找它,但没有找到解决方案。。。也许你对我期望的结果有一个解决方案
我已经学会并试着制作db小提琴,以便于其他人使用
[更新]已解决
要查看上述案例的更新,您可以在db fiddle上查看更新查询,也许您只是在寻找一个案例表达式,如下所示:
SELECT
ScanIn
, case
when ScanIn < '07:00:00' then '21:00:00'
when ScanIn < '14:00:00' then '07:00:00'
when ScanIn < '21:00:00' then '14:00:00'
end as WorkhourIn
...
这与你在问题中表达条件的方式非常相似。案例表达式的计算结果为每行一个值首先,对于将来的问题,请不要在发布时使用图像。使用文本,让任何想要帮助的人都能更快地生成您的场景。有关更多信息,请参阅评论中的 那么,关于你的问题,让我们从简单的事情开始。由于您使用的是MariaDB 10.4+,这是一个好消息,因为该版本支持更新的功能;在这里,我将演示其中一个;行号,请参考官方 基本查询如下所示:
SELECT ROW_NUMBER() OVER (PARTITION BY DATE ORDER BY DATE, TIME) AS row_num,
id, MachineIp, FingerId, DATE, TIME, STATUS, Verified, DateCreated
FROM HrAttLogs;
ROW_NUMBER在这里所做的是为按日期划分的每一行分配行号排名,并按日期、时间和顺序进行排序;给你这个:
+---------+------+-------------+----------+------------+----------+--------+----------+---------------------+
| row_num | id | MachineIp | FingerId | DATE | TIME | STATUS | Verified | DateCreated |
+---------+------+-------------+----------+------------+----------+--------+----------+---------------------+
| 1 | 12 | 10.20.20.73 | 2 | 2019-12-26 | 07:54:25 | 0 | 1 | 2019-12-26 11:09:21 |
| 2 | 216 | 10.20.20.73 | 2 | 2019-12-24 | 16:23:10 | 1 | 1 | 2019-12-26 11:09:21 |
| 1 | 272 | 10.20.20.73 | 2 | 2019-12-24 | 07:52:25 | 0 | 1 | 2019-12-26 11:09:21 |
| 1 | 426 | 10.20.20.73 | 2 | 2019-12-23 | 07:43:44 | 0 | 1 | 2019-12-26 11:09:22 |
| 1 | 709 | 10.20.20.73 | 2 | 2019-12-30 | 07:28:42 | 0 | 1 | 2019-12-30 09:54:21 |
| 2 | 913 | 10.20.20.73 | 2 | 2019-12-28 | 14:05:05 | 1 | 1 | 2019-12-30 09:54:22 |
| 1 | 978 | 10.20.20.73 | 2 | 2019-12-28 | 07:22:32 | 0 | 1 | 2019-12-30 09:54:22 |
| 1 | 1468 | 10.20.20.73 | 2 | 2019-12-31 | 17:57:16 | 1 | 1 | 2020-01-02 10:08:45 |
| 2 | 1796 | 10.20.20.73 | 2 | 2020-01-09 | 18:04:37 | 1 | 1 | 2020-01-10 09:50:28 |
| 1 | 1892 | 10.20.20.73 | 2 | 2020-01-09 | 07:51:52 | 0 | 1 | 2020-01-10 09:50:29 |
| 1 | 2079 | 10.20.20.73 | 2 | 2020-01-08 | 06:56:55 | 0 | 1 | 2020-01-10 09:50:29 |
| 2 | 2163 | 10.20.20.73 | 2 | 2020-01-07 | 16:21:30 | 1 | 1 | 2020-01-10 09:50:29 |
| 1 | 2221 | 10.20.20.73 | 2 | 2020-01-07 | 07:51:57 | 0 | 1 | 2020-01-10 09:50:29 |
+---------+------+-------------+----------+------------+----------+--------+----------+---------------------+
请注意开头的row_num字段。然后将其作为子查询,并在第_num行上使用CASE表达式执行GROUP_CONCAT,以获取datein、dateout、scanin和scan out:
SELECT fingerid,
GROUP_CONCAT(CASE WHEN row_num=1 THEN DATE END) AS datein,
GROUP_CONCAT(CASE WHEN row_num=2 THEN DATE END) AS dateout,
GROUP_CONCAT(CASE WHEN row_num=1 THEN TIME END) AS scanin,
GROUP_CONCAT(CASE WHEN row_num=2 THEN TIME END) AS scanout
FROM (SELECT ROW_NUMBER() OVER (PARTITION BY DATE ORDER BY DATE, TIME) AS row_num,
id, MachineIp, FingerId, DATE, TIME, STATUS, Verified, DateCreated
FROM HrAttLogs) A
GROUP BY DATE;
上述查询将返回以下结果:
+----------+------------+------------+-----------+----------+
| fingerid | datein | dateout | scanin | scanout |
+----------+------------+------------+-----------+----------+
| 2 | 2019-12-23 | | 07:43:44 | |
| 2 | 2019-12-24 | 2019-12-24 | 07:52:25 | 16:23:10 |
| 2 | 2019-12-26 | | 07:54:25 | |
| 2 | 2019-12-28 | 2019-12-28 | 07:22:32 | 14:05:05 |
| 2 | 2019-12-30 | | 07:28:42 | |
| 2 | 2019-12-31 | | 17:57:16 | |
| 2 | 2020-01-07 | 2020-01-07 | 07:51:57 | 16:21:30 |
| 2 | 2020-01-08 | | 06:56:55 | |
| 2 | 2020-01-09 | 2020-01-09 | 07:51:52 | 18:04:37 |
+----------+------------+------------+-----------+----------+
从这里,您可以开始在其他表上使用JOIN来获取更多信息。查询的最后一部分只是使用下面的CASE表达式分配WorkhourIn和Workhourout:
SELECT *,
CASE WHEN scanin < '07:00:00' THEN '21:00:00'
WHEN scanin < '14:00:00' THEN '07:00:00'
WHEN scanin < '21:00:00' THEN '14:00:00' END AS 'WorkHourIn',
CASE WHEN scanin < '07:00:00' THEN '07:00:00'
WHEN scanin < '14:00:00' THEN '14:00:00'
WHEN scanin < '21:00:00' THEN '21:00:00' END AS 'WorkHourOut'
FROM
(SELECT fingerid,
GROUP_CONCAT(CASE WHEN row_num=1 THEN DATE END) AS datein,
GROUP_CONCAT(CASE WHEN row_num=2 THEN DATE END) AS dateout,
GROUP_CONCAT(CASE WHEN row_num=1 THEN TIME END) AS scanin,
GROUP_CONCAT(CASE WHEN row_num=2 THEN TIME END) AS scanout
FROM (SELECT ROW_NUMBER() OVER (PARTITION BY DATE ORDER BY DATE, TIME) AS row_num,
id, MachineIp, FingerId, DATE, TIME, STATUS, Verified, DateCreated
FROM HrAttLogs) A
GROUP BY DATE) B ;
现在我知道这对你来说是一个全新的查询,但正如我所说的,可能有一种方法可以大大缩短你原来的查询,我在一开始就打算这么做。希望这将是有用的
顺便说一句,这里是小提琴为所有上述:
更新
有关后续问题,请尝试以下方法:
SELECT i.FingerId,fs.ShiftId,MIN(i.Date) AS 'Date',
/*added CASE expression to deal with overlapping attendance date*/
CASE WHEN MIN(i.Time) >= '21:00:00'
THEN DATE(DATE_ADD(i.Date, INTERVAL + 1 DAY))
ELSE DATE(DATE_ADD(i.Date, INTERVAL + s.DayOut DAY)) END AS 'DateOut',
MIN(i.Time) AS 'Time',
s.ShiftIn_1,s.ShiftIn_2,s.ShiftIn_3,s.ShiftOut_1,s.ShiftOut_2,s.ShiftOut_3,
s.WorkhourIn_1,s.WorkhourIn_2,s.WorkhourIn_3,s.WorkhourOut_1,
s.WorkhourOut_2,s.WorkhourOut_3
FROM HrAttLogs AS i
INNER JOIN HrEmployee AS fs ON fs.FingerId = i.FingerId
INNER JOIN HrEmployeeShift AS s ON s.Id = fs.ShiftId
WHERE i.Time >= s.ShiftIn_1
AND i.Date >= '2020-01-01'
AND i.Date <= '2020-01-10'
AND i.MachineIp = '10.20.20.73'
GROUP BY i.FingerId, i.date
/*added check for date too.. the last checking is for any overlapping date*/
CASE WHEN i.dateout = i.date AND i.Time > i.ShiftOut_1 THEN i.WorkhourOut_2
WHEN i.dateout = i.date AND i.Time > i.ShiftOut_2 THEN i.WorkhourOut_3
WHEN i.dateout = i.date AND i.Time > i.ShiftOut_3 THEN i.WorkhourOut_1
WHEN i.dateout > i.date THEN i.WorkhourOut_3
END AS WorkhourOut,
让我们从简单的事情开始。我认为主要有3个表有问题:HrAttLogs、HrEmployee和HrEmployeeShift。为我们提供这三个表的数据示例,每个表5-10行,并向我们展示一个预期输出的示例。如果可以的话会更好。您好,@tcadidot0谢谢您的输入,我会解决它的。是的,我可以看到您正在尝试做什么,而且我以前有一点处理考勤数据的经验。我开始的时候几乎和你一样,有一个很长的查询,但经过几次测试后,我的查询明显更短,更易于阅读/维护。希望我们能对你的情况做同样的事情:我很高兴听到这个消息,我希望你能用你的经验帮助我:非常感谢你之前。。。我已经更新了@tcadidot0的数据,目前我可以想出三种方法来实现这一点。。但是首先,我可以知道你使用的是什么版本的MySQL吗?您能否快速运行SELECT@@version查找?非常感谢您提供的输入,我将很快更正我提出的问题,在我从未使用db FIDLE之前,这将是未来的一次新体验。请参考,我已经将您的许多参考资料应用到查询中,但显然出现了一个新的案例,我在问题中进行了更新。感谢更新,我尝试使用WorkhourOut表达式,但在“字段列表”中出现错误“I.DateOut”,我尝试使用db FIDLE。请您检查此Alhamdulillah,这是完全成功的,非常感谢。还有一个问题与如何删除更多字段选择有关,如ShiftIn_1、ShiftIn_2、ShiftIn_3等。。但是他们需要拜访queryAlhamdulillah,这很好。我不太明白你说的删除更多字段是什么意思,但如果你想只显示选定字段,只需更改第一个SELECT*。。选择FingerId、ShiftId、DateIn、DateOut、ScanIn、ScanOut、WorkhourIn、WorkhourOut、TIME\u IN、TIME\u OUT。
SELECT i.FingerId,fs.ShiftId,MIN(i.Date) AS 'Date',
/*added CASE expression to deal with overlapping attendance date*/
CASE WHEN MIN(i.Time) >= '21:00:00'
THEN DATE(DATE_ADD(i.Date, INTERVAL + 1 DAY))
ELSE DATE(DATE_ADD(i.Date, INTERVAL + s.DayOut DAY)) END AS 'DateOut',
MIN(i.Time) AS 'Time',
s.ShiftIn_1,s.ShiftIn_2,s.ShiftIn_3,s.ShiftOut_1,s.ShiftOut_2,s.ShiftOut_3,
s.WorkhourIn_1,s.WorkhourIn_2,s.WorkhourIn_3,s.WorkhourOut_1,
s.WorkhourOut_2,s.WorkhourOut_3
FROM HrAttLogs AS i
INNER JOIN HrEmployee AS fs ON fs.FingerId = i.FingerId
INNER JOIN HrEmployeeShift AS s ON s.Id = fs.ShiftId
WHERE i.Time >= s.ShiftIn_1
AND i.Date >= '2020-01-01'
AND i.Date <= '2020-01-10'
AND i.MachineIp = '10.20.20.73'
GROUP BY i.FingerId, i.date
/*added check for date too.. the last checking is for any overlapping date*/
CASE WHEN i.dateout = i.date AND i.Time > i.ShiftOut_1 THEN i.WorkhourOut_2
WHEN i.dateout = i.date AND i.Time > i.ShiftOut_2 THEN i.WorkhourOut_3
WHEN i.dateout = i.date AND i.Time > i.ShiftOut_3 THEN i.WorkhourOut_1
WHEN i.dateout > i.date THEN i.WorkhourOut_3
END AS WorkhourOut,