sql >> Database teknologi >  >> RDS >> Sqlserver

Sådan identificeres det første hul i flere start- og slutdatointervaller for hvert enkelt medlem i T-SQL

Prøv dette:http://www.sqlfiddle.com/#!3/c3365/ 20

with s as
(
  select *, row_number() over(partition by membercode order by startdate) rn
  from tbl
)
,gaps as
(
select a.membercode, a.startdate, a.enddate, b.startdate as nextstartdate
  ,datediff(d, a.enddate, b.startdate) as gap
from s a
join s b on b.membercode = a.membercode and b.rn = a.rn + 1
)
select membercode 
from gaps
group by membercode
having sum(case when gap <= 1 then 1 end) = count(*);
 

Se forespørgselsforløbet her:http://www.sqlfiddle.com/#!3/ c3365/20

Sådan fungerer det, sammenlign den aktuelle slutdato med dens næste startdato og kontroller datogabet:

with s as
(
  select *, row_number() over(partition by membercode order by startdate) rn
  from tbl
)
select a.membercode, a.startdate, a.enddate, b.startdate as nextstartdate
  ,datediff(d, a.enddate, b.startdate) as gap
from s a
join s b on b.membercode = a.membercode and b.rn = a.rn + 1;
 

Output:

| MEMBERCODE | STARTDATE | ENDDATE | NEXTSTARTDATE | GAP | -------------------------------------------------------------- | 1 | 2010-01-15 | 2010-01-20 | 2010-01-19 | -1 | | 1 | 2010-01-19 | 2010-01-22 | 2010-01-20 | -2 | | 1 | 2010-01-20 | 2010-01-25 | 2010-01-26 | 1 | | 2 | 2010-01-20 | 2010-01-25 | 2010-01-30 | 5 | | 2 | 2010-01-30 | 2010-02-05 | 2010-02-04 | -1 |

Kontroller derefter, om et medlem har samme antal krav uden huller i forhold til dets samlede krav:

with s as
(
  select *, row_number() over(partition by membercode order by startdate) rn
  from tbl
)
,gaps as
(
select a.membercode, a.startdate, a.enddate, b.startdate as nextstartdate
  ,datediff(d, a.enddate, b.startdate) as gap
from s a
join s b on b.membercode = a.membercode and b.rn = a.rn + 1
)
select membercode, count(*) as count, sum(case when gap <= 1 then 1 end) as gapless_count
from gaps
group by membercode;
 

Output:

| MEMBERCODE | COUNT | GAPLESS_COUNT | -------------------------------------- | 1 | 3 | 3 | | 2 | 2 | 1 |

Filtrer dem til sidst, medlemmer uden huller i deres krav:

with s as
(
  select *, row_number() over(partition by membercode order by startdate) rn
  from tbl
)
,gaps as
(
select a.membercode, a.startdate, a.enddate, b.startdate as nextstartdate
  ,datediff(d, a.enddate, b.startdate) as gap
from s a
join s b on b.membercode = a.membercode and b.rn = a.rn + 1
)
select membercode 
from gaps
group by membercode
having sum(case when gap <= 1 then 1 end) = count(*);
 

Output:

| MEMBERCODE | -------------- | 1 |

Bemærk, at du ikke behøver at gøre COUNT(*) > 1 at opdage medlemmer med 2 eller flere krav. I stedet for at bruge LEFT JOIN , vi bruger JOIN , vil dette automatisk kassere medlemmer, der endnu ikke har et andet krav. Her er versionen (længere), hvis du vælger at bruge LEFT JOIN i stedet (samme output som ovenfor):

with s as
(
select *, row_number() over(partition by membercode order by startdate) rn
from tbl
)
,gaps as
(
select a.membercode, a.startdate, a.enddate, b.startdate as nextstartdate
,datediff(d, a.enddate, b.startdate) as gap
from s a
left join s b on b.membercode = a.membercode and b.rn = a.rn + 1
)
select membercode 
from gaps
group by membercode
having sum(case when gap <= 1 then 1 end) = count(gap)
and count(*) > 1; -- members who have two ore more claims only
 

Sådan ser du data fra ovenstående forespørgsel før filtrering:

with s as
(
  select *, row_number() over(partition by membercode order by startdate) rn
  from tbl
)
,gaps as
(
select a.membercode, a.startdate, a.enddate, b.startdate as nextstartdate
  ,datediff(d, a.enddate, b.startdate) as gap
from s a
left join s b on b.membercode = a.membercode and b.rn = a.rn + 1
)
select * from gaps;
 

Output:

| MEMBERCODE | STARTDATE | ENDDATE | NEXTSTARTDATE | GAP | ----------------------------------------------------------------- | 1 | 2010-01-15 | 2010-01-20 | 2010-01-19 | -1 | | 1 | 2010-01-19 | 2010-01-22 | 2010-01-20 | -2 | | 1 | 2010-01-20 | 2010-01-25 | 2010-01-26 | 1 | | 1 | 2010-01-26 | 2010-01-30 | (null) | (null) | | 2 | 2010-01-20 | 2010-01-25 | 2010-01-30 | 5 | | 2 | 2010-01-30 | 2010-02-05 | 2010-02-04 | -1 | | 2 | 2010-02-04 | 2010-02-15 | (null) | (null) | | 3 | 2010-02-15 | 2010-03-02 | (null) | (null) |

REDIGER om kravafklaring:

På din præcisering ønskede du også at inkludere medlemmer, der endnu ikke har fået et andet krav, gør dette i stedet:http://sqlfiddle.com/#!3/c3365/22

with s as
(
select *, row_number() over(partition by membercode order by startdate) rn
from tbl
)
,gaps as
(
select a.membercode, a.startdate, a.enddate, b.startdate as nextstartdate
,datediff(d, a.enddate, b.startdate) as gap
from s a
left join s b on b.membercode = a.membercode and b.rn = a.rn + 1
)
select membercode 
from gaps
group by membercode
having sum(case when gap <= 1 then 1 end) = count(gap)
-- members who have yet to have a second claim are valid too
or count(nextstartdate) = 0; 
 

Output:

| MEMBERCODE | -------------- | 1 | | 3 |

Teknikken er at tælle medlemmets nextstartdate , hvis de ikke har nogen næste startdato(dvs. count(nextstartdate) = 0 ) så er de kun enkeltkrav og også gyldige, så vedhæft bare denne OR tilstand:

or count(nextstartdate) = 0; 
 

Faktisk vil betingelsen nedenfor også være tilstrækkelig, jeg ønskede dog at gøre forespørgslen mere selvdokumenterende, derfor anbefaler jeg at regne med medlemmets næste startdato. Her er en alternativ betingelse for at tælle medlemmer, der endnu ikke har fået et nyt krav:

or count(*) = 1;
 

Btw, vi er også nødt til at ændre sammenligningen fra dette:

sum(case when gap <= 1 then 1 end) = count(*)
 

til dette (da vi bruger LEFT JOIN nu):

sum(case when gap <= 1 then 1 end) = count(gap)
 


  1. Mysql vælg efter bedste match med like

  2. Sådan overføres parametre til mysql-forespørgselstilbagekald i nodejs

  3. MySQL Type=MyISAM-fejl

  4. mysql opdatering qty på komplet ordre array