ЕСЛИ 3 или более условия QUERY MySQL - PullRequest
0 голосов
/ 11 апреля 2020

Спасибо за просмотр моего вопроса о IF 3 или более условиях. QUERY MySQL.

После того, как я узнал по ссылке , опубликованной Strawberry в комментариях, я получил больше информации. изучите и улучшите мой вопрос здесь, через несколько дней я исправил его в столбце ответов ниже, и результаты были такими: у меня новый случай с моим Query, надеюсь, вы поможете мне решить эту проблему ..

Запрос из таблицы HrAttLogs:

| FingerId | MachineIp   | Date       | Time     | Status | Verified | DateCreated         |
| -------- | ----------- | ---------- | -------- | ------ | -------- | ------------------- |
| 2        | 10.20.20.73 | 2020-01-03 | 07:20:13 | 0      | 1        | 2020-01-10 09:50:30 |
| 2        | 10.20.20.73 | 2020-01-03 | 14:05:00 | 1      | 1        | 2020-01-10 09:50:30 |
| 2        | 10.20.20.73 | 2020-01-06 | 17:22:18 | 0      | 1        | 2020-01-10 09:50:29 |
| 2        | 10.20.20.73 | 2020-01-07 | 16:21:30 | 0      | 1        | 2020-01-10 09:50:29 |
| 2        | 10.20.20.73 | 2020-01-07 | 21:51:57 | 1      | 1        | 2020-01-10 09:50:29 |
| 2        | 10.20.20.73 | 2020-01-08 | 06:56:55 | 0      | 1        | 2020-01-10 09:50:29 |
| 2        | 10.20.20.73 | 2020-01-09 | 21:10:00 | 0      | 1        | 2020-01-10 09:50:28 |
| 2        | 10.20.20.73 | 2020-01-10 | 04:05:05 | 1      | 1        | 2020-01-10 09:50:29 |

Мы можем видеть, где поле Status содержит 0 и 1 , где 0 mean In и 1 mean Exit

В данных, которые у меня есть:

| 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 показывает день после DateIn, который равен 2020-01-10 (можно увидеть в HrAttLogs Query), где ScanOut должен отображаться в 04:05:05. Как мне это получить? Я искал это, но не нашел решения ... может быть, у вас есть решение для результатов, которые я ожидаю

Я выучил и попытался создать скрипку БД, чтобы облегчить ее для других Ссылка здесь

[ОБНОВЛЕНО] РЕШЕНО

Чтобы увидеть обновления из приведенного выше случая, вы можете увидеть запрос на обновление в db fiddle здесь

Ответы [ 2 ]

1 голос
/ 13 апреля 2020

Прежде всего, для будущих вопросов, пожалуйста, воздержитесь от использования изображения при публикации. Вместо этого используйте текст, чтобы любой, кто намеревается помочь, мог быстрее генерировать ваш сценарий. Пожалуйста, обратитесь к ссылке , опубликованной Strawberry в комментарии для получения дополнительной информации.

Итак, по вашему вопросу давайте начнем с чего-то простого. Поскольку вы используете MariaDB 10.4+, это хорошая новость, поскольку эта версия поддерживает новые функции; и здесь я собираюсь продемонстрировать один из них; ROW_NUMBER(), см. Официальные документы MariaDB здесь .

Базовый запрос таков:

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 в начале. Затем сделайте это как подзапрос и выполните GROUP_CONCAT с CASE выражением для row_num, чтобы получить datein, dateout, scanin и scan:

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 на других таблицах для получения дополнительной информации. Последняя часть запроса состоит в том, чтобы просто присвоить WorkhourIn и Workhourout, используя выражение CASE, как показано ниже:

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 ;

Это даст вам результат:

+----------+------------+------------+----------+----------+------------+-------------+
| fingerid |   datein   |  dateout   |  scanin  | scanout  | WorkHourIn | WorkHourOut |
+----------+------------+------------+----------+----------+------------+-------------+
|        2 | 2019-12-23 |            | 07:43:44 |          | 07:00:00   | 14:00:00    |
|        2 | 2019-12-24 | 2019-12-24 | 07:52:25 | 16:23:10 | 07:00:00   | 14:00:00    |
|        2 | 2019-12-26 |            | 07:54:25 |          | 07:00:00   | 14:00:00    |
|        2 | 2019-12-28 | 2019-12-28 | 07:22:32 | 14:05:05 | 07:00:00   | 14:00:00    |
|        2 | 2019-12-30 |            | 07:28:42 |          | 07:00:00   | 14:00:00    |
|        2 | 2019-12-31 |            | 17:57:16 |          | 14:00:00   | 21:00:00    |
|        2 | 2020-01-07 | 2020-01-07 | 07:51:57 | 16:21:30 | 07:00:00   | 14:00:00    |
|        2 | 2020-01-08 |            | 06:56:55 |          | 21:00:00   | 07:00:00    |
|        2 | 2020-01-09 | 2020-01-09 | 07:51:52 | 18:04:37 | 07:00:00   | 14:00:00    |
+----------+------------+------------+----------+----------+------------+-------------+

Сейчас Я знаю, что это совершенно новый запрос для вас, но, как я уже сказал, может быть способ значительно сократить исходный запрос, и я стремился к этому в начале. Надеюсь, это будет полезно.

Кстати, вот скрипка для всего вышеперечисленного: https://www.db-fiddle.com/f/riiCi8tjtMaBk64fG6hd4K/0

Обновление Для последующего вопрос, попробуйте следующее:

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

Тогда ваше CASE выражение для WorkhourOut изменится на следующее:

/*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, 
1 голос
/ 11 апреля 2020

Возможно, вы просто ищете case expression, например:

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

, что очень похоже на то, как вы выразили условие в своем вопросе. case expression оценивается как одно значение (на строку)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...