Coba ini: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(*);
Lihat perkembangan kueri di sini:http://www.sqlfiddle.com/#!3/ c3365/20
Cara kerjanya, bandingkan tanggal akhir saat ini dengan tanggal mulai berikutnya dan periksa kesenjangan tanggal:
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;
Keluaran:
| 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 |
Kemudian periksa apakah anggota memiliki jumlah klaim yang sama tanpa kesenjangan dengan total klaimnya:
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;
Keluaran:
| MEMBERCODE | COUNT | GAPLESS_COUNT |
--------------------------------------
| 1 | 3 | 3 |
| 2 | 2 | 1 |
Terakhir, filter mereka, anggota tanpa celah dalam klaim mereka:
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(*);
Keluaran:
| MEMBERCODE |
--------------
| 1 |
Perhatikan bahwa Anda tidak perlu melakukan COUNT(*) > 1
untuk mendeteksi anggota dengan 2 atau lebih klaim. Alih-alih menggunakan LEFT JOIN
, kami menggunakan JOIN
, ini akan secara otomatis membuang anggota yang belum memiliki klaim kedua. Inilah versinya (lebih lama) jika Anda memilih untuk menggunakan LEFT JOIN
sebagai gantinya (keluaran yang sama seperti di atas):
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
Berikut cara melihat data query di atas sebelum difilter:
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;
Keluaran:
| 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) |
EDIT tentang klarifikasi persyaratan:
Pada klarifikasi Anda, Anda ingin menyertakan anggota yang belum memiliki klaim kedua juga, lakukan ini sebagai gantinya: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;
Keluaran:
| MEMBERCODE |
--------------
| 1 |
| 3 |
Tekniknya adalah dengan menghitung nextstartdate
. anggota , jika mereka tidak memiliki tanggal mulai berikutnya (yaitu count(nextstartdate) = 0
) maka mereka hanya klaim tunggal dan valid juga, lalu lampirkan OR
ini kondisi:
or count(nextstartdate) = 0;
Sebenarnya, kondisi di bawah ini juga sudah cukup, saya ingin membuat kueri lebih mendokumentasikan diri sendiri, oleh karena itu saya sarankan untuk menghitung tanggal mulai anggota berikutnya. Berikut kondisi alternatif untuk menghitung anggota yang belum memiliki klaim kedua:
or count(*) = 1;
Btw, kita juga harus mengubah perbandingan dari ini:
sum(case when gap <= 1 then 1 end) = count(*)
untuk ini (karena kami menggunakan LEFT JOIN
sekarang):
sum(case when gap <= 1 then 1 end) = count(gap)