Sqlserver
 sql >> Teknologi Basis Data >  >> RDS >> Sqlserver

Cara mengidentifikasi kesenjangan pertama dalam beberapa rentang tanggal mulai dan akhir untuk setiap anggota berbeda di T-SQL

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)


  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Cari Tahu apakah Objek adalah Fungsi Bernilai Tabel di SQL Server dengan OBJECTPROPERTY()

  2. Pernyataan BERGABUNG Bersyarat SQL Server

  3. Bagaimana Anda menentukan Tabel SQL apa yang memiliki kolom identitas secara terprogram?

  4. Bagaimana menemukan SQL Server menjalankan port?

  5. Bagaimana cara mengubah gambar ke array byte menggunakan javascript hanya untuk menyimpan gambar di server sql?