Опитайте това: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,dateddiff(d, a.enddate, b.startdate) като gapfrom s ajoin s b на b.membercode =a.membercode и b.rn =a.rn + 1)изберете членски код от gapsgroup по membercodehaving sum(случай, когато празнината <=1 след това 1 край) =count(*);
Вижте напредъка на заявката тук:http://www.sqlfiddle.com/#!3/ c3365/20
Как работи, сравнете текущата крайна дата със следващата начална дата и проверете разликата в датата:
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) като gapfrom s ajoin s b на b.membercode =a.membercode и b.rn =a.rn + 1;
Изход:
<предварителен код>| КОД НА ЧЛЕН | НАЧАЛНА ДАТА | КРАЙНА ДАТА | СЛЕДВАЩА НАЧАЛНА ДАТА | GAP |------------------------------------------------ --------------| 1 | 15 януари 2010 | 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 | 04.02.2010 | -1 |След това проверете дали даден член има същия брой искове без пропуски спрямо общия му брой:
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 ,dateddiff(d, a.enddate, b.startdate) as gapfrom s ajoin s b on b.membercode =a.membercode и b.rn =a.rn + 1)изберете membercode, count(*) като count, sum( случай, когато празнина <=1 след това 1 край) като gapless_countfrom gapsgroup по членски код;
Изход:
<предварителен код>| КОД НА ЧЛЕН | БРОЯ | GAPLESS_COUNT |--------------------------------------------| 1 | 3 | 3 || 2 | 2 | 1 |Накрая ги филтрирайте, членове без пропуски в твърденията си:
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,dateddiff(d, a.enddate, b.startdate) като gapfrom s ajoin s b на b.membercode =a.membercode и b.rn =a.rn + 1)изберете членски код от gapsgroup по membercodehaving sum(случай, когато празнината <=1 след това 1 край) =count(*);
Изход:
<предварителен код>| КОД НА ЧЛЕН |--------------| 1 |
Имайте предвид, че не е необходимо да правите COUNT(*)> 1
за откриване на членове с 2 или повече искания. Вместо да използвате LEFT JOIN
, ние използваме JOIN
, това автоматично ще отхвърли членове, които все още нямат втори иск. Ето версията (по-дълга), ако решите да използвате LEFT JOIN
вместо това (същият изход като по-горе):
with s as(select *, row_number() over(partition by membercode order by startdate) rnfrom tbl),gaps as(select a.membercode, a.startdate, a.enddate, b.startdate as nextstartdate ,dateddiff(d, a.enddate, b.startdate) като gapfrom s отляво се присъедини към s b на b.membercode =a.membercode и b.rn =a.rn + 1)изберете членски код от gapsgroup чрез membercodehaving sum(случай, когато празнината <=1 след това 1 край) =броене (празнина) и броене (*)> 1; -- членове, които имат само две или повече претенции
Ето как да видите данните от горната заявка преди филтриране:
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 ,dateddiff(d, a.enddate, b.startdate) as gapfrom s left join s b on b.membercode =a.membercode and b.rn =a.rn + 1)select * from gaps;
Изход:
<предварителен код>| КОД НА ЧЛЕН | НАЧАЛНА ДАТА | КРАЙНА ДАТА | СЛЕДВАЩА НАЧАЛНА ДАТА | GAP |------------------------------------------------ ------------------| 1 | 15 януари 2010 | 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 | (нула) | (нула) || 2 | 2010-01-20 | 2010-01-25 | 2010-01-30 | 5 || 2 | 2010-01-30 | 2010-02-05 | 04.02.2010 | -1 || 2 | 04.02.2010 | 2010-02-15 | (нула) | (нула) || 3 | 2010-02-15 | 2010-03-02 | (нула) | (null) |РЕДАКТИРАНЕ при изясняване на изискването:
Според вашето пояснение, искахте да включите и членове, които все още не са имали втори иск, направете това вместо това:http://sqlfiddle.com/#!3/c3365/22
with s as(select *, row_number() over(partition by membercode order by startdate) rnfrom tbl),gaps as(select a.membercode, a.startdate, a.enddate, b.startdate as nextstartdate ,dateddiff(d, a.enddate, b.startdate) като gapfrom s отляво се присъедини към s b на b.membercode =a.membercode и b.rn =a.rn + 1)изберете членски код от gapsgroup чрез membercodehaving sum(случай, когато празнината <=1 след това 1 край) =count(gap)-- членовете, които тепърва ще имат втори иск, също са валидни или count(nextstartdate) =0;
Изход:
<предварителен код>| КОД НА ЧЛЕН |--------------| 1 || 3 |
Техниката е да се преброи nextstartdate
на члена , ако нямат следваща начална дата (т.е. count(nextstartdate) =0
), тогава те са само единични искове и също са валидни, тогава просто прикачете това ИЛИ
състояние:
или count(nextstartdate) =0;
Всъщност условието по-долу също ще е достатъчно, но исках да направя заявката по-самодокументираща се, затова препоръчвам да разчитате на следващата начална дата на члена. Ето едно алтернативно условие за преброяване на членове, които все още нямат втори иск:
или count(*) =1;
Между другото, ние също трябва да променим сравнението от това:
sum(case when gap <=1 then 1 end) =count(*)
към това (тъй като използваме LEFT JOIN
сега):
сума (случай, когато интервал <=1, след това 1 край) =брой (празнина)