Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/mysql/56.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如果有3个或更多条件查询MySQL_Mysql_Sql - Fatal编程技术网

如果有3个或更多条件查询MySQL

如果有3个或更多条件查询MySQL,mysql,sql,Mysql,Sql,感谢您看到我关于是否有3个或更多条件查询MySQL的问题 在我从评论中了解更多信息后,我开始研究并改进我的问题,几天后我从下面的回答栏中更正了它,结果是这样的,我的问题有了一个新的案例,希望你能帮助我解决这个问题 从HrAttLogs表中查询: 我们可以看到状态字段包含0和1,其中0表示进入,1表示退出 在我掌握的数据中: | FingerId | ShiftId | DateIn | DateOut | ScanIn | ScanOut | WorkhourIn | Wor

感谢您看到我关于是否有3个或更多条件查询MySQL的问题

在我从评论中了解更多信息后,我开始研究并改进我的问题,几天后我从下面的回答栏中更正了它,结果是这样的,我的问题有了一个新的案例,希望你能帮助我解决这个问题

从HrAttLogs表中查询:

我们可以看到状态字段包含0和1,其中0表示进入,1表示退出

在我掌握的数据中:

| 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,