Как выбрать записи, которые выпадают на определенную дату, а затем появляются позже? - PullRequest
0 голосов
/ 07 ноября 2019

У меня есть таблица с записями, которые проверяются ежегодно. То, что я хотел бы проверить, - это записи, которые были проверены до 3/01/2014, но затем выпали и были забраны 11.03.2009.

Например, где максимальная дата = 3/1/2014 до того, как 3/1/2019 была записана в тот же идентификатор. Однако возвращаемая запись также должна включать в себя адрес 3/1/2019.

Mytable:

ID  |Date
1   |3/1/2011
1   |3/1/2012
1   |3/1/2013
1   |3/1/2014    
2   |3/1/2011
2   |3/1/2012
2   |3/1/2013
2   |3/1/2014
2   |3/1/2019
3   |3/1/2011
3   |3/1/2012
3   |3/1/2013
3   |3/1/2014
3   |3/1/2015
3   |3/1/2019

Для приведенного выше примера я хотел бы, чтобы идентификатор 2 возвращался как еготолько запись, которая соответствует критериям.

Результат

ID
2

ID 1 не включает 3/1/2019, поэтому он был исключен.

ID 3 имеет максимальную датуот 01.03.2015, предшествовавшего дате 3/1/2019, и исключен.

Ответы [ 3 ]

1 голос
/ 07 ноября 2019

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

select id
from t
group by id
having max(case when date < date '2019-11-03' then date end) < date '2014-03-01' and
       sum(case when date = date '2019-11-03' then 1 else 0 end) > 0;

Альтернативный метод:

select t.*
from (select t.*,
             lag(date) over (partition by id order by date) as prev_date
      from t
     ) t
where date = date '2019-11-03' and
      prev_date < date '2019-03-01';
0 голосов
/ 07 ноября 2019

Рассмотрим MATCH_RECOGNIZE.

Есть много способов SQL сделать это, некоторые хорошие уже даны. Вот тот, который ( очень возможно) более читабелен, когда вы освоитесь с синтаксисом.

Вы ищете строки в ваших данных, которые соответствуют шаблону. В частности, за строкой до 01.03.2014 или после нее следует сразу же за строкой от 01.03.2009, между которой ничего нет.

Каждый раз, когда вы ищете строки, соответствующие шаблону, вы можете использоватьпредложение MATCH_RECOGNIZE в вашем SELECT. Вот ваш случай:

SELECT id from mytable
MATCH_RECOGNIZE (
  PARTITION BY id
  ONE ROW PER MATCH
  PATTERN ( OLDER RECENT )
  DEFINE
    RECENT AS RECENT.dte = TO_DATE('3/1/2019','MM/DD/YYYY'),
    OLDER AS OLDER.dte <= TO_DATE('3/1/2014','MM/DD/YYYY')
)
+----+
| ID |
+----+
|  2 |
+----+

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

Например, предположим, что вы также хотели знать, для каждого id, какова была дата выпадения серии. (То есть, это была последняя дата или до 01.03.2014, для которой были данные). Это подходит только с небольшими изменениями:

SELECT id, dropoff_date from mytable
MATCH_RECOGNIZE (
  PARTITION BY id
  MEASURES OLDER.dte AS dropoff_date
  ONE ROW PER MATCH
  PATTERN ( OLDER RECENT )
  DEFINE
    RECENT AS RECENT.dte = TO_DATE('3/1/2019','MM/DD/YYYY'),
    OLDER AS OLDER.dte <= TO_DATE('3/1/2014','MM/DD/YYYY')
)
+----+--------------+
| ID | DROPOFF_DATE |
+----+--------------+
|  2 | 01-MAR-14    |
+----+--------------+
0 голосов
/ 07 ноября 2019

Я не уверен в синтаксисе, который у вас есть, но в postgresql вы могли бы написать так, как этот код, в mysql, если я не ошибаюсь, вы должны изменить боковое для применения и т. Д.

SELECT distinct id from my_table a
left join lateral(select count(distinct date) b4 from my_table b where b.id=a.id and date<='3/01/2014') befor on true
left join lateral(select count(distinct date) aftr from my_table b where b.id=a.id and date>='3/11/2019') after on true
where b4>0 and aftr>0

В основномчто я делаю, так это присоединяюсь к количеству дат до и после указанных дат, а затем показываю только отдельные идентификаторы, которые имеют оба.

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