sql >> Database >  >> RDS >> Sqlserver

Hoe de eerste kloof in meerdere begin- en einddatumbereiken te identificeren voor elk afzonderlijk lid in T-SQL

Probeer dit: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(*);

Bekijk de voortgang van de zoekopdracht hier:http://www.sqlfiddle.com/#!3/ c3365/20

Hoe het werkt, vergelijk de huidige einddatum met de volgende startdatum en controleer het datumgat:

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;

Uitgang:

| 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 |

Controleer vervolgens of een lid hetzelfde aantal claims heeft zonder hiaten in het totale aantal claims:

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;

Uitgang:

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

Filter ze tot slot, leden zonder hiaten in hun claims:

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(*);

Uitgang:

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

Houd er rekening mee dat u COUNT(*) > 1 . niet hoeft te doen om leden met 2 of meer claims te detecteren. In plaats van LEFT JOIN . te gebruiken , we gebruiken JOIN , verwijdert dit automatisch leden die nog een tweede claim moeten hebben. Dit is de versie (langer) als je ervoor kiest om LEFT JOIN te gebruiken in plaats daarvan (dezelfde uitvoer als hierboven):

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

Zo ziet u de gegevens van de bovenstaande zoekopdracht voorafgaand aan het filteren:

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;

Uitgang:

| 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) |

BEWERKEN op verzoek verduidelijking:

Ter verduidelijking, je wilde leden opnemen die nog geen tweede claim hebben, doe dit in plaats daarvan: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; 

Uitgang:

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

De techniek is om de nextstartdate van het lid te tellen , als ze geen volgende startdatum hebben (d.w.z. count(nextstartdate) = 0 ) dan zijn het alleen enkele claims en ook geldig, voeg dan gewoon deze OR . toe staat:

or count(nextstartdate) = 0; 

Eigenlijk is de onderstaande voorwaarde ook voldoende, ik wilde de zoekopdracht echter meer zelfdocumenterend maken, daarom raad ik aan te rekenen op de volgende startdatum van het lid. Hier is een alternatieve voorwaarde voor het tellen van leden die nog een tweede claim hebben:

or count(*) = 1;

Trouwens, we moeten hier ook de vergelijking van veranderen:

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

hieraan (omdat we LEFT JOIN gebruiken) nu):

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


  1. HQL is null En !=null op een Oracle-kolom

  2. pdo-variabele is niet gedefinieerd in mysql-functie

  3. Selecteer alles waar [eerste letter begint met B]

  4. Geen toegang tot Sonar MySQL-database Veroorzaakt door:java.sql.SQLException:Toegang geweigerd voor gebruiker 'sonar'@'glassfishdev.ccs.local' (met wachtwoord:JA)