Versuchen Sie Folgendes: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(*);
Siehe Abfragefortschritt hier:http://www.sqlfiddle.com/#!3/ c3365/20
So funktioniert es:Vergleichen Sie das aktuelle Enddatum mit dem nächsten Startdatum und überprüfen Sie die Datumslücke:
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;
Ausgabe:
| 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 |
Überprüfen Sie dann, ob ein Mitglied die gleiche Anzahl von Ansprüchen ohne Lücken zu seinen Gesamtansprüchen hat:
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;
Ausgabe:
| MEMBERCODE | COUNT | GAPLESS_COUNT |
--------------------------------------
| 1 | 3 | 3 |
| 2 | 2 | 1 |
Filtern Sie sie schließlich, Mitglieder ohne Lücken in ihren Ansprüchen:
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(*);
Ausgabe:
| MEMBERCODE |
--------------
| 1 |
Beachten Sie, dass Sie COUNT(*) > 1
nicht ausführen müssen um Mitglieder mit 2 oder mehr Ansprüchen zu erkennen. Anstatt LEFT JOIN
zu verwenden verwenden wir JOIN
, werden dadurch automatisch Mitglieder ausgeschlossen, die noch keinen zweiten Anspruch haben. Hier ist die (längere) Version, wenn Sie sich für LEFT JOIN
entscheiden stattdessen (gleiche Ausgabe wie oben):
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
So sehen Sie Daten der obigen Abfrage vor dem Filtern:
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;
Ausgabe:
| 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) |
BEARBEITEN zur Anforderungsklärung:
Bei Ihrer Klarstellung wollten Sie auch Mitglieder einbeziehen, die noch keinen zweiten Anspruch haben, tun Sie dies stattdessen: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;
Ausgabe:
| MEMBERCODE |
--------------
| 1 |
| 3 |
Die Technik besteht darin, das nextstartdate
des Mitglieds zu zählen , wenn sie kein Datum für das nächste Startdatum haben (d. h. count(nextstartdate) = 0
) dann sind es nur Einzelansprüche und auch gültig, dann hänge einfach diesen OR
an Bedingung:
or count(nextstartdate) = 0;
Eigentlich reicht die folgende Bedingung auch aus, ich wollte die Abfrage aber selbstdokumentierender machen, daher empfehle ich, auf das nächste Startdatum des Mitglieds zu zählen. Hier ist eine alternative Bedingung für das Zählen von Mitgliedern, die noch keinen zweiten Anspruch haben:
or count(*) = 1;
Übrigens müssen wir auch den Vergleich hiervon ändern:
sum(case when gap <= 1 then 1 end) = count(*)
dazu (da wir LEFT JOIN
verwenden jetzt):
sum(case when gap <= 1 then 1 end) = count(gap)