Sqlserver
 sql >> Baza danych >  >> RDS >> Sqlserver

Jak zidentyfikować pierwszą lukę w wielu zakresach dat rozpoczęcia i zakończenia dla każdego odrębnego elementu w T-SQL?

Spróbuj tego: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(*);

Zobacz postęp zapytania tutaj:http://www.sqlfiddle.com/#!3/ c3365/20

Jak to działa, porównaj bieżącą datę zakończenia z następną datą rozpoczęcia i sprawdź różnicę dat:

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;

Wyjście:

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

Następnie sprawdź, czy członek ma taką samą liczbę roszczeń bez luk w łącznej liczbie roszczeń:

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;

Wyjście:

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

Na koniec odfiltruj ich, członków bez luk w swoich roszczeniach:

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

Wyjście:

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

Pamiętaj, że nie musisz wykonywać COUNT(*) > 1 aby wykryć członków z 2 lub więcej roszczeniami. Zamiast używać LEFT JOIN , używamy JOIN , spowoduje to automatyczne odrzucenie członków, którzy nie mają jeszcze drugiego roszczenia. Oto wersja (dłuższa), jeśli zdecydujesz się użyć LEFT JOIN zamiast tego (to samo wyjście co powyżej):

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

Oto jak wyświetlić dane powyższego zapytania przed filtrowaniem:

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;

Wyjście:

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

EDYTUJ w sprawie wyjaśnienia wymagań:

W swoim wyjaśnieniu chcesz uwzględnić członków, którzy jeszcze nie mają drugiego roszczenia, zrób to: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; 

Wyjście:

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

Technika polega na zliczeniu nextstartdate członka , jeśli nie mają daty następnej daty rozpoczęcia (tj. count(nextstartdate) = 0 ), to są to tylko pojedyncze oświadczenia i są one również ważne, a następnie po prostu dołącz ten OR warunek:

or count(nextstartdate) = 0; 

Właściwie warunek poniżej też wystarczy, chciałem jednak, aby zapytanie było bardziej samodokumentujące, dlatego polecam liczyć na następną datę startową użytkownika. Oto alternatywny warunek liczenia członków, którzy nie mają jeszcze drugiego roszczenia:

or count(*) = 1;

Btw, musimy również zmienić porównanie z tego:

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

do tego (ponieważ używamy LEFT JOIN teraz):

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. Wstawianie danych SQL Server do Salesforce.com

  2. Skryptowanie konfiguracji poczty bazy danych

  3. Jaka jest maksymalna liczba kolumn dozwolona w widoku SQL Server 2008?

  4. Dostawca OLE DB Microsoft.ACE.OLEDB.12.0 dla serwera połączonego (null) zwrócił komunikat Zakładka jest nieprawidłowa.

  5. Błąd we/wy:nieudane logowanie jednokrotne:natywna biblioteka SSPI nie została załadowana