Запрос T-SQL для определения диапазонов дат при возникновении события - PullRequest
0 голосов
/ 23 мая 2018

Я пытаюсь определить диапазоны дат, когда организация входит в наш список "мониторов".

Мои данные выглядят так:

OrgCode OrgName           ReviewDate    MonitorList
8000    Organization A    3/6/2014      1
8000    Organization A    6/4/2014      1
8000    Organization A    9/4/2014      1
8000    Organization A    12/4/2014     0
8000    Organization A    3/5/2015      1
8000    Organization A    6/4/2015      1
8000    Organization A    9/16/2015     1
8000    Organization A    12/16/2015    1
8000    Organization A    3/9/2016      1
8000    Organization A    6/2/2016      1
8000    Organization A    9/8/2016      1
8000    Organization A    12/8/2016     1
8000    Organization A    3/9/2017      0
8000    Organization A    6/14/2018     0

Вывод запроса, который я ищувыглядит следующим образом:

OrgCode OrgName           MonitorStartDate  MonitorEndDate
8000    Organization A    3/6/2014          12/4/2014
8000    Organization A    3/5/2015          3/9/2017

Эта организация, Организация A, появилась в нашем списке мониторов дважды: с 6 марта 2014 года по 4 сентября 2014 года и с 5 марта 2015 года по 3 марта/2017.

Я пытался сделать это несколькими способами, в том числе,

  • Разновидности LEAD() и LAG()
  • GROUP BY OrgCode, OrgName, MonitorList и определения MonitorStartDate как MIN(ReviewDate) и MonitorEndDate как MAX(ReviewDate).

Второй метод не учитывает тот факт, что эти организации могут быть /из списка мониторов несколько раз.Я все еще думаю, что некоторые комбинации LEAD() или LAG() могут работать;но не сами по себе.

Любое руководство, которое вы, ребята, можете дать, было бы замечательно, и спасибо за помощь!

Ответы [ 3 ]

0 голосов
/ 23 мая 2018

Вы можете идентифицировать группы, посчитав число 0 в * или после каждой строки.Остальное просто агрегация:

select orgcode, orgname, min(ReviewDate) as MonitorStartDate,
       coalesce(min(case when monitorlist = 0 then ReviewDate end),
                max(ReviewDate)
               ) as MontiroEndDate
from (select t.*,
             sum(case when monitorlist = 0 then 1 else 0 end) over (partition by orgcode order by reviewdate desc) as grp             
      from t
     ) t
group by orgcode, orgname, grp
having max(monitorlist) = 1;

Логика для даты окончания немного хитрая:

  • Это ReviewDate записи "0".
  • Если их нет, используется последний ReviewDate.

Здесь - это скрипта SQL, демонстрирующая это.

0 голосов
/ 23 мая 2018

С этим запросом

select orgcode,orgname,format(min(reviewdate),'M/d/yyyy') as monitorstartdate,format(max(next_dt),'M/d/yyyy') as monitorenddate
from (select t.*,
   sum(case when monitorlist=0 then 1 else 0 end) 
     over(partition by orgcode order by reviewdate) as grp,
     lead(reviewdate) over(partition by orgcode order by reviewdate) as next_dt
   from tbl t
   ) t
group by orgcode,orgname,grp,MonitorList
having MonitorList = 1

результат будет следующим:

orgcode     orgname             monitorstartdate    monitorenddate
8000        "Organization A"    3/6/2014            12/4/2014
8000        "Organization A"    3/5/2015            3/9/2017

Ссылка Fiddle здесь , если люди хотят проверить.

0 голосов
/ 23 мая 2018

Используйте промежуточную сумму, чтобы классифицировать строки по группам, переустанавливая значение, когда встречается 0, и lead, чтобы получить дату следующей строки, потому что конечная дата должна быть с первой встреченной 0.Затем используйте min и max в соответствующих столбцах с необходимыми группировками.

select orgcode,orgname
,min(case when monitorlist=1 then reviewdate end) as monitorstartdate
,max(next_dt) as monitorenddate
from (select t.*,
      sum(case when monitorlist=0 then 1 else 0 end) over(partition by orgcode order by reviewdate) as grp,
      lead(reviewdate) over(partition by orgcode order by reviewdate) as next_dt
      from tbl t
     ) t
group by orgcode,orgname,grp
having max(cast(monitorlist as int))=1
...