SQL - Выберите последнюю запись на основе нескольких условий - PullRequest
3 голосов
/ 02 мая 2020

У меня есть следующая таблица.

+----+--------+--------+------------+
| ID | Parent | Status |    Date    |
+----+--------+--------+------------+
|  1 |    667 | O      | 2019-09-23 |
|  1 |    667 | O      | 2019-10-01 |
|  1 |    667 | C      | 2019-10-12 |
|  1 |    667 | O      | 2019-10-31 |
| 33 |    566 | C      | 2019-09-28 |
| 33 |    566 | C      | 2019-10-03 |
| 33 |    566 | C      | 2019-10-17 |
| 33 |    566 | C      | 2019-10-23 |
| 33 |    566 | C      | 2019-10-29 |
|  2 |    667 | O      | 2019-10-01 |
|  2 |    667 | O      | 2019-10-12 |
|  2 |    667 | C      | 2019-10-31 |
| 34 |    566 | O      | 2019-10-03 |
| 34 |    566 | O      | 2019-10-17 |
| 34 |    566 | C      | 2019-10-23 |
| 34 |    566 | C      | 2019-10-29 |
+----+--------+--------+------------+

Теперь мне нужно найти все ID в таблице между 2019-10-01 и 2019-10-31, которые имели статус O во время этого период и имеет статус C согласно последней записи.

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

+----+--------+--------+------------+
| ID | Parent | Status |    Date    |
+----+--------+--------+------------+
|  2 |    667 | C      | 2019-10-31 |
| 34 |    566 | C      | 2019-10-29 |
+----+--------+--------+------------+

Я попытался сделать запрос

SELECT ID, Parent, Status, Date
FROM tabe WHERE Status='C' AND DATE >= '2019-10-01' AND Date <= '2019-10-31' AND ID IN (
    SELECT DISTINCT ID FROM tabe WHERE Status='O' AND Date >= '2019-10-01' AND Date <= '2019-10-31'
);

и получил следующий вывод

+----+--------+--------+------------+
| ID | Parent | Status |    Date    |
+----+--------+--------+------------+
|  1 |    667 | C      | 2019-10-12 |
|  2 |    667 | C      | 2019-10-31 |
| 34 |    566 | C      | 2019-10-23 |
| 34 |    566 | C      | 2019-10-29 |
+----+--------+--------+------------+

Любая помощь очень ценится.

1 Ответ

1 голос
/ 02 мая 2020

Вы указываете, что хотите идентификаторы. Таким образом, вы можете использовать агрегацию и предложение having:

select id
from t
where date >= '2019-10-01' and date < '2019-11-01'
group by id
having sum( status = 'O' ) > 0 and
       max(case when status = 'C' then date end) = max(date);

Если вы действительно хотите исходные строки, вы можете использовать JOIN, IN, EXISTS или оконные функции. Для последнего:

select t.*
from (select t.*,
             sum(status = 'O') over (partition by id) as num_os,
             first_value(status) over (partition by id order by date desc) as last_status
      from t
      where date >= '2019-10-01' and date < '2019-11-01'
     ) t
where num_os > 0 and last_status = 'C';
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...