Sqlserver
 sql >> база данни >  >> RDS >> Sqlserver

Как да идентифицирате първата празнина в множество начални и крайни диапазони от дати за всеки отделен член в T-SQL

Опитайте това: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 край) =брой (празнина) 


  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Извличане/избиране на стойности от множество редове в 1 единствен ред в sql сървър

  2. SQL Server 2016:Въздействие върху производителността на винаги криптирани

  3. Комбиниране на редове от търсени резултати по уникален идентификатор?

  4. DECODE( ) функция в SQL Server

  5. SQL Server 2008 Разделена таблица и паралелизъм