Очень сложный SQL-запрос - PullRequest
0 голосов
/ 22 апреля 2019

Я использую MySql и должен создать очень сложный отчет, который показывает состояние событий.

Например:

event_id   |  state        |  create_time
----------------------------------------------------
1          |    PENDING    | 2019-04-21 12:55:59.312
1          |   COMPLETED   | 2019-04-21 12:55:59.339
2          |   PENDING     | 2019-04-21 11:40:21.699
3          |   PENDING     | 2019-04-21 11:40:21.699
3          |   FAILED      | 2019-04-21 11:40:21.600
3          |   COMPLETED   | 2019-04-21 11:40:21.578

Мне нужно выбрать строки в соответствии с предпочтениями состояний:

  • СБОЙ + ЗАВЕРШЕНО + В ОЖИДАНИИ -> СБОЙ
  • ЗАВЕРШЕНО + В ОЖИДАНИИ -> ЗАВЕРШЕНО
  • В ОЖИДАНИИ -> В ОЖИДАНИИ

Это должно быть разбито на страницы с использованием OFFSET и SIZE.

Каждое событие будет показано один раз.

ожидаемый результат:

event_id   |  state        |  create_time
----------------------------------------------------
1          |   COMPLETED   | 2019-04-21 12:55:59.339
2          |   PENDING     | 2019-04-21 11:40:21.699
3          |   FAILED      | 2019-04-21 11:40:21.600

Как я могу сделать это в одном запросе SQL.

С уважением, Идо

Ответы [ 3 ]

3 голосов
/ 22 апреля 2019

Я подозреваю, что вы хотите агрегировать с некоторой условной логикой, например:

select event_id,
       (case when sum(state = 'FAILED') > 0 then 'FAILED'
             when sum(state = 'COMPLETED') > 0 then 'COMPLETED'
             when sum(state = 'PENDING') > 0 then 'PENDING'
        end) as new_state
from t
group by event_id;
2 голосов
/ 22 апреля 2019

Вы можете сделать агрегацию с coalesce():

select event_id,
       coalesce(max(case when state = 'FAILED' then 'FAILED' end),
                max(case when state = 'COMPLETED' then 'COMPLETED' end),
                'PENDING'     
               )
from table t
group by event_id;
1 голос
/ 22 апреля 2019

Другой вариант - обрабатывать эти состояния состояний как битовые маски.

Примечание Этот метод предполагает, что для event_id нет дублирующихся статистических данных.

Запрос

SELECT 
 t.*
FROM (

SELECT 
   t.event_id
 , SUM(bitmask_table.bitmask) AS total_bitmask
FROM (
  SELECT
    DISTINCT 
       state
     , CASE 
        WHEN state = 'PENDING'
        THEN 2

        WHEN state = 'COMPLETED'
        THEN 4

        WHEN state = 'FAILED'
        THEN 8
       END AS bitmask
  FROM
   t 
) AS bitmask_table
INNER JOIN 
 t
ON
 t.state = bitmask_table.state
GROUP BY 
 t.event_id

) AS group_bitmasked
INNER JOIN 
 t
ON
  group_bitmasked.event_id = t.event_id
AND
 t.state = CASE
    WHEN group_bitmasked.total_bitmask & 8 AND group_bitmasked.total_bitmask & 4 AND  group_bitmasked.total_bitmask & 2
    THEN 'FAILED'

    WHEN group_bitmasked.total_bitmask & 4 AND group_bitmasked.total_bitmask & 2
    THEN 'COMPLETED'  

    WHEN group_bitmasked.total_bitmask & 2
    THEN 'PENDING'      
   END

Результат

| event_id | state     | create_time             |
| -------- | --------- | ----------------------- |
| 1        | COMPLETED | 2019-04-21 12:55:59.339 |
| 2        | PENDING   | 2019-04-21 11:40:21.699 |
| 3        | FAILED    | 2019-04-21 11:40:21.600 |

см. демо

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