SQL: Величайшая строка с переменной группа / условие - PullRequest
0 голосов
/ 21 сентября 2018

У меня есть эта упрощенная таблица, документирующая некоторые прогоны заданий:

+----+-----------------------+--------+
| id |          pit          |  stat  |
+----+-----------------------+--------+
|  1 | '2018-09-21 12:00:00' | 'TEST' |
|  1 | '2018-09-20 12:00:00' | 'TEST' |
|  1 | '2018-09-19 12:00:00' | 'PROD' |
|  1 | '2018-09-18 12:00:00' | 'PROD' |
|  1 | '2018-09-17 12:00:00' | 'TEST' |
|    |                       |        |
|  2 | '2018-09-19 14:00:00' | 'TEST' |
|  2 | '2018-09-18 14:00:00' | 'TEST' |
|    |                       |        |
|  3 | '2018-09-19 15:00:00' | 'PROD' |
|  3 | '2018-09-18 15:00:00' | 'PROD' |
|  3 | '2018-09-17 15:00:00' | 'TEST' |
|    |                       |        |
|  4 | '2018-09-21 12:00:00' | 'PROD' |
|  4 | '2018-09-20 12:00:00' | 'PROD' |
+----+-----------------------+--------+

Теперь я хочу сделать следующее:

Для каждого идентификатора: Найти последний прогон задания.Если последний прогон имеет stat = 'PROD', верните только эту строку.Если последний прогон имеет stat = 'TEST', верните эту строку и дополнительно верните последний прогон с stat = 'PROD'.

В настоящее время я запускаю этот SQL для получения самого последнего прогона PROD, а также самого последнего прогона TEST для каждого идентификатора:

SELECT t.*
FROM SOME_TABLE t
INNER JOIN (
    SELECT id, MAX(pit) pit, stat
    FROM SOME_TABLE
    GROUP BY id, stat
) mt ON t.id = mt.id AND t.pit = mt.pit
ORDER BY id asc, pit desc;

SQL Fiddle

Теперь, чего мне не хватает, так это той части, которую я хочу отфильтровать с помощью stat = 'TEST', если есть более поздний запуск с stat = 'PROD'.

Есть ли хороший способ?достижения этого в SQL?

Ответы [ 2 ]

0 голосов
/ 21 сентября 2018
 with tmp as (
          select SOME_TABLE.* from SOME_TABLE 
          inner join (Select MAX(pit) as pit,
          id from SOME_TABLE group by id) t on t.id = SOME_TABLE.id 
          and t.pit = SOME_TABLE.pit),
    tmp2 as(
          Select MAX(SOME_TABLE.pit) as pit, SOME_TABLE.id, SOME_TABLE.stat 
          from SOME_TABLE 
          inner join tmp on tmp.id = SOME_TABLE.id and tmp.stat = 'TEST'
          where SOME_TABLE.stat = 'PROD'
          group by SOME_TABLE.id, SOME_TABLE.stat
    )
   select * from tmp2
   union 
   select * from tmp
   ORDER BY id, pit desc
0 голосов
/ 21 сентября 2018

Иногда перефразирование требования может помочь.Здесь для каждого идентификатора вы хотите вернуть самую последнюю строку и самую последнюю строку «prod», которая может быть или не быть одной и той же строкой.Альтернативный способ взглянуть на проблему - отсортировать строки двумя способами и взять первую строку из каждой категории:

  1. В порядке убывания по дате (чтобы получить самую последнюю), в соответствии сID
  2. В порядке возрастания по типу (чтобы получить строки "prod" перед строками "test"), а затем в порядке убывания по дате, для идентификатора:

SELECT id, pit, stat
FROM   (SELECT id, pit, stat
               ROW_NUMBER() OVER (PARTITION BY id ORDER BY pit DESC) AS rn,
               ROW_NUMBER() OVER (PARTITION BY id ORDER BY stat ASC, pit DESC) AS prn
        FROM   some_table) t
WHERE  1 IN (rn, prn)
...