2014-10-01 3 views
0

아래 샘플 표에서 해당하는 경우 S의 첫 번째 인스턴스보다 먼저 event_type CP의 마지막 인스턴스를 반환하는 스크립트가 필요합니다. 기본 비교는 가장 최근의 event_date입니다. 날짜가 중복되는 경우 타이 브레이?가 가장 높은 event_id가됩니다.여러 열을 기반으로 한 테이블 반환

person_id event_date   event_id event_type 
78   08/12/2010 00:00 706   CP 
78   09/12/2010 00:00 707   CP 
107   23/02/2010 00:00 93   CP 
107   21/09/2012 00:00 1474  S 
217   18/02/2010 00:00 158   S 
364   26/01/2011 00:00 1122  CP 
364   19/02/2011 00:00 569   S 
367   21/06/2010 00:00 151   CP 
367   01/07/2010 00:00 247   S 
369   26/07/2010 00:00 248   S 
369   27/07/2010 00:00 152   CP 
481   07/09/2010 00:00 194   CP 
481   07/09/2010 00:00 289   S 
502   13/08/2010 00:00 200   CP 
530   14/06/2010 00:00 220   CP 
535   05/07/2010 00:00 222   CP 
535   26/07/2010 00:00 224   CP 
536   23/08/2010 00:00 225   CP 
631   15/12/2009 00:00 256   CP 
632   18/09/2010 00:00 259   CP 
643   18/09/2010 00:00 261   CP 
653   30/09/2010 00:00 360   S 
653   15/10/2010 00:00 295   CP 
653   15/10/2010 00:00 298   CP 
680   30/09/2010 00:00 281   CP 
680   30/11/2010 00:00 480   CP 
689   06/10/2010 00:00 372   S 
689   02/11/2010 00:00 306   CP 
689   02/11/2010 00:00 370   CP 
689   26/08/2011 00:00 1944  CP 
689   27/08/2011 00:00 1947  CP 
689   22/09/2011 00:00 2125  CP 
689   06/11/2012 00:00 2720  CP 
689   13/11/2012 00:00 2752  CP 
689   15/11/2012 00:00 2765  CP 
729   15/09/2010 00:00 299   CP 
811   27/10/2010 00:00 413   S 
834   06/01/2012 00:00 1233  S 
849   21/02/2011 00:00 336   CP 
984   13/11/2010 00:00 384   CP 
984   18/11/2010 00:00 392   CP 
984   18/11/2010 00:00 395   CP 
984   19/11/2010 00:00 394   CP 
1066  11/11/2010 00:00 472   S 
1066  23/11/2010 00:00 408   CP 
1109  23/12/2010 00:00 428   CP 
1109  19/07/2011 00:00 958   S 
1190  02/12/2010 00:00 499   CP 
1193  03/12/2010 00:00 504   CP 
1194  03/12/2010 00:00 505   CP 
1199  19/11/2010 00:00 511   CP 
1199  19/11/2010 00:00 501   S 
1199  05/12/2010 00:00 526   CP 
1199  08/12/2010 00:00 568   CP 
1199  16/12/2010 00:00 704   CP 
1199  16/12/2010 00:00 705   CP 
1199  23/12/2010 00:00 803   CP 
1199  24/12/2010 00:00 809   CP 
1199  31/12/2010 00:00 851   CP 
1199  11/01/2011 00:00 926   CP 
1199  15/02/2011 00:00 1119  CP 
1199  03/03/2011 00:00 1116  CP 
1199  28/07/2011 00:00 1726  CP 
1199  26/08/2011 00:00 1943  CP 
1199  03/09/2011 00:00 1984  CP 
1199  21/09/2011 00:00 2064  CP 
1209  05/12/2010 00:00 524   CP 
1210  05/12/2010 00:00 525   CP 
1383  20/12/2010 00:00 798   CP 
1386  20/12/2010 00:00 799   CP 
1404  23/12/2010 00:00 801   CP 
1405  23/12/2010 00:00 802   CP 
1444  31/12/2010 00:00 849   CP 
1445  31/12/2010 00:00 850   CP 
1535  11/01/2011 00:00 924   CP 
1536  11/01/2011 00:00 925   CP 
1565  09/01/2011 00:00 979   CP 
1623  27/01/2011 00:00 531   S 
1661  25/01/2011 00:00 1046  CP 
1662  25/01/2011 00:00 1047  CP 
1663  25/01/2011 00:00 1048  CP 
1665  25/01/2011 00:00 1049  CP 
1666  23/01/2011 00:00 1050  CP 
1667  01/02/2011 00:00 1052  CP 
1741  14/02/2011 00:00 1111  CP 
1752  15/02/2011 00:00 1118  CP 
1781  04/10/2010 00:00 1868  CP 
1781  04/10/2010 00:00 1869  CP 
1781  04/10/2010 00:00 1870  CP 
1781  10/02/2011 00:00 1052  S 
1781  25/03/2011 00:00 1867  CP 
1781  26/09/2011 00:00 2103  CP 
1841  02/02/2011 00:00 1165  CP 
1841  28/02/2011 00:00 597   S 
1845  13/06/2011 00:00 1608  CP 
1845  14/06/2011 00:00 1605  CP 
1845  16/06/2011 00:00 1602  CP 
1845  16/06/2011 00:00 1609  CP 
1845  16/06/2011 00:00 1610  CP 
1880  22/07/2011 00:00 1684  CP 
1887  11/03/2011 00:00 1231  CP 
1887  18/03/2011 00:00 607   S 
1903  02/06/2011 00:00 1551  CP 
1913  25/03/2011 00:00 1301  CP 
1913  31/03/2011 00:00 1354  CP 
2054  11/05/2011 00:00 1447  CP 
2054  12/05/2011 00:00 780   S 
2103  03/04/2011 00:00 1417  CP 
2109  17/04/2011 00:00 1422  CP 
2123  09/04/2011 00:00 1434  CP 
2123  05/05/2011 00:00 769   S 
2187  20/01/2011 00:00 1475  CP 
2187  29/01/2011 00:00 803   S 
2222  12/05/2011 00:00 1501  CP 
2246  31/05/2011 00:00 1536  CP 
2246  02/06/2011 00:00 1539  CP 
2246  01/07/2012 00:00 1448  S 
2246  29/07/2012 00:00 2569  CP 
2246  06/08/2012 00:00 2586  CP 
2306  06/05/2011 00:00 918   S 
2456  15/09/2011 00:00 2065  CP 
2456  02/12/2013 00:00 1694  S 
2456  29/01/2014 00:00 3340  CP 
2456  01/10/2014 00:00 3661  CP 
2459  24/08/2011 00:00 1859  CP 
2476  17/08/2011 00:00 1039  S 
2512  17/09/2011 00:00 2049  CP 
2512  26/01/2012 00:00 1256  S 
2516  24/08/2011 00:00 1857  CP 
2630  03/09/2011 00:00 1982  CP 
2630  13/05/2013 00:00 3064  CP 
2691  22/09/2011 00:00 2135  CP 
2694  20/04/2011 00:00 2053  CP 
2694  30/04/2011 00:00 1112  S 
2759  07/11/2011 00:00 1165  S 
2759  09/01/2012 00:00 2271  CP 
2759  09/02/2012 00:00 2377  CP 
2773  24/01/2013 00:00 2920  CP 
2773  25/01/2013 00:00 1430  S 
2773  14/02/2013 00:00 2946  CP 
2858  27/10/2011 00:00 2209  CP 
2858  08/11/2011 00:00 1167  S 
2892  05/11/2011 00:00 1172  S 
2896  09/11/2011 00:00 1174  S 
2961  15/08/2012 00:00 2591  CP 
3041  28/03/2012 00:00 2441  CP 
3041  29/03/2012 00:00 2442  CP 
3178  08/09/2012 00:00 2611  CP 
3251  13/11/2012 00:00 2744  CP 
3263  28/11/2012 00:00 2802  CP 
3294  14/12/2012 00:00 2826  CP 
3311  01/02/2013 00:00 1534  S 
3344  30/04/2013 00:00 1566  S 
3344  03/05/2013 00:00 3045  CP 
3362  07/02/2013 00:00 2980  CP 
3362  06/04/2013 00:00 1555  S 
3426  22/05/2013 00:00 3086  CP 
3457  29/11/2012 00:00 1574  S 
3612  10/11/2012 00:00 3551  CP 
3770  03/01/2014 00:00 3379  CP 
3770  10/01/2014 00:00 1766  S 
3805  04/03/2014 00:00 1782  S 
3881  05/04/2014 00:00 3550  CP 
3901  15/02/2014 00:00 3584  CP 
3901  02/03/2014 00:00 1820  S 
3907  04/11/2013 00:00 1821  S 
3907  06/01/2014 00:00 3591  CP 
3907  14/01/2014 00:00 3592  CP 
3907  14/01/2014 00:00 3593  CP 
4040  10/05/2014 00:00 3660  CP 
4040  15/05/2014 00:00 3659  CP 
4040  20/05/2014 00:00 1866  S 

답변

0

당신은 ROW_NUMBER를 사용

select * from (
    select *, 
    row_number() over (partition by person_id order by event_date desc) rn 
    from (
     select * 
     from mytable t1 
     where not exists (
      select 1 from mytable t2 
      where t2.event_type = 'S' 
      and t2.person_id = t1.person_id 
      and t2.event_date < t1.event_date 
     ) and event_type = 'CP' 
    ) t1 
) t1 where rn = 1 
+2

** LEAD **는 SQL Server 2012 이상 버전에서만 지원됩니다. SQL Server 2005 **의 OP 태그가 질문에 표시되었습니다. –

1

예 (첫 번째 S 전에 즉 마지막 CP) 그 행의 마지막 CP을 선택하기 위해 모든 처음 S 이전 CProw_number()을 선택 not exists을 사용할 수 있습니다 (), SQL Server 2005에서 지원됩니다.

[편집 :이 버전은 실제 데이터 일부 person_id로 년대 일부 person_id로 년대 또는 S의 여러 인스턴스에 대한 S 형 (이 그 첫 번째 인스턴스 전에 S와 다른 코드의 첫 번째 인스턴스를 얻을 것이다)]

with tab as 
(
select 3907 as person_id, 2457 as event_id, '01/09/2013 00:00' as event_date, 'CP' as event_type 
union 
select 3907 as person_id, 2896 as event_id, '09/09/2013 00:00' as event_date, 'CP' as event_type 
union 
select 3907 as person_id, 1866 as event_id, '20/05/2014 00:00' as event_date, 'S' as event_type 
union 
select 4040 as person_id, 3660 as event_id, '10/05/2014 00:00' as event_date, 'CP' as event_type 
union 
select 4040 as person_id, 3659 as event_id, '15/05/2014 00:00' as event_date, 'CP' as event_type 
union 
select 4040 as person_id, 1866 as event_id, '20/05/2014 00:00' as event_date, 'S' as event_type 
) 
,personsAndFirst_S_Type as 
(
    select 
     person_id, 
     min(event_date) as first_S_EventDate 
    from tab 
    where event_type = 'S' 
    group by person_id 
) 
, 
numberedTab as 
(
    select 
     *, 
     ROW_NUMBER() OVER(PARTITION BY person_id ORDER BY event_type, event_date, event_id) as rn 
    from tab 
) 
,maxRn as 
(
    select 
     person_id, 
     max(rn) as maxNonSRow 
    from numberedTab nt 
    where nt.event_type <> 'S' 
    group by person_id 
) 
select 
    numberedTab.person_id, 
    numberedTab.event_id, 
    numberedTab.event_date, 
    numberedTab.event_type 
from numberedTab 
inner join maxRn 
    on numberedTab.rn = maxRn.maxNonSRow 
    and numberedTab.person_id = maxRn.person_id 
inner join personsAndFirst_S_Type s 
    on numberedTab.person_id = s.person_id 
    and numberedTab.event_date < s.first_S_EventDate 

사용 TSQL의 리드 기능이없는 경우 등 상황이있다 그러나 모든 행에서 다음 행의 event_type 열을 가져 오려면 해당 파티션을 분할하고 순서를 지정해야합니다. 내가 여기에 제대로 이해한다면

MSDN Page on TSQL LEAD Function

with tab as 
(
select 3907 as person_id, 2457 as event_id, '01/09/2013 00:00' as event_date, 'CP' as event_type 
union 
select 3907 as person_id, 2896 as event_id, '09/09/2013 00:00' as event_date, 'CP' as event_type 
union 
select 3907 as person_id, 1866 as event_id, '20/05/2014 00:00' as event_date, 'S' as event_type 
union 
select 4040 as person_id, 3660 as event_id, '10/05/2014 00:00' as event_date, 'CP' as event_type 
union 
select 4040 as person_id, 3659 as event_id, '15/05/2014 00:00' as event_date, 'CP' as event_type 
union 
select 4040 as person_id, 1866 as event_id, '20/05/2014 00:00' as event_date, 'S' as event_type 
), 
tabWithNextEventTypeOnRow as 
(
    select 
     *, 
     LEAD(event_type) OVER(PARTITION BY person_id ORDER BY event_date) as nxtEventType 
    from tab 
) 
select 
    * 
from tabWithNextEventTypeOnRow 
where nxtEventType = 'S' 
+1

** LEAD **는 SQL Server 2012 이상 버전에서만 지원됩니다. SQL Server 2005 **의 OP 태그가 질문에 표시되었습니다. –

+0

나는 그것을 보지 못했다. 지적 해 주셔서 고마워요, Krishnraj. SQL Server 2005에서 지원되는 ROW_NUMBER()를 사용하는 추가 단계 CTE 버전이 있습니다. – Bpa

+0

@Bpa LEAD() 함수가없는 스크립트는 person_id 값 1199, 1781, 2246, 2456, 2773. 이것은 person_id의 이러한 인스턴스가 S의 첫 번째 인스턴스 이후뿐만 아니라 S의 첫 번째 인스턴스 이후에 CP의 인스턴스를 가지기 때문인 것으로 보입니다.이 인스턴스는 스크립트에서 준비 할 수 있습니까? 감사합니다 –

0

당신은 당신이 원하는 것입니다.

스키마

Declare @table1 table (person_id int, event_id int, event_date varchar(30), event_type varchar(5)) 
insert into @table1 values 
(3907,2457 ,'01/09/2013', 'CP'), 
(3907,2896 ,'09/09/2013', 'CP'), 
(3907,1866 ,'20/05/2013', 'S'), 
(4040,3660 ,'10/05/2014', 'CP'), 
(4040,3659 ,'15/05/2014', 'CP'), 
(4040,1866 ,'20/05/2014', 'S') 

문을 다시 제외하고에 쿼리

SELECT person_id, event_id, event_date, event_type 
FROM (
    SELECT * 
     ,ROW_NUMBER() OVER (
      PARTITION BY person_id ORDER BY event_date DESC 
      ) rownum 
    FROM @table1 
    WHERE event_type = 'CP' 
    ) t 
WHERE rownum = 1 

출력

person_id event_id event_date event_type 
3907  2896   09/09/2013 CP 
4040  3659   10/05/2014 CP 
+0

이것은 사람마다 마지막 cp를 반환합니다. op는 첫 번째 s 전에 마지막 cp를 원합니다. – FuzzyTree

+0

@FuzzyTree : 지적 해 주셔서 감사합니다. –

+0

@Krishnraj Rana 업데이트 해 주셔서 감사합니다. 스크립트가 person_id 당 여러 줄을 반환하고 있습니다. 나는 이제 더 포괄적 인 표를 추가했다. LEAD() 함수를 사용하지 않는 Bpa의 스크립트는 좋은 결과를 보여 주지만 S의 첫 번째 인스턴스 앞에 CP 인스턴스가있는 person_id의 인스턴스에 대해서만 행을 리턴합니다. event_type의 인스턴스가있는 person_id 값은 생략하고 있습니다. CP의 값은 S의 첫 번째 인스턴스 전과 후에 나타납니다. 설명이 약간 길면 유감 스럽습니다! –

0

노조 필요한 모든 행을 바꿉니다. 심지어 CP의 인스턴스가있는 인스턴스도 S의 첫 번째 인스턴스 전후에 있습니다. 이보다 효율적인 솔루션이 있어야하지만 시간과 리소스는 현재 내 광우병이 아닙니다.

select person_id,event_date,event_id,rn from 
    (select *, 
    row_number() over (partition by person_id order by event_date desc, event_id desc) rn 
    from (select * 
     from mytable t1 
     where not exists 
     (select 1 from mytable t2 
     where t2.event_type = 'S' AND 
     t2.person_id = t1.person_id AND 
     t2.event_date <= t1.event_date) 
     AND event_type = 'CP') t1) t1 where rn = 1 
union 
select person_id,event_date,event_id,rn from 
(select *, 
row_number() over (partition by person_id order by event_date desc, event_id desc) rn 
from (select * 
     from mytable t1 
     where not exists 
     (select 1 from mytable t2 
     where t2.event_type = 'S' AND 
     t2.person_id = t1.person_id AND 
     t2.event_date <> t1.event_date) 
     AND event_type = 'CP') t1) t1 where rn = 1 
except 
select person_id,event_date,event_id,rn from 
(select *, 
row_number() over (partition by person_id order by event_date desc, event_id desc) rn 
from (select * 
     from mytable t1 
     where not exists 
     (select 1 from mytable t2 
     where t2.event_type = 'S' AND 
     t2.person_id = t1.person_id AND 
     t2.event_date <= t1.event_date) 
     AND event_type = 'CP') t1) t1 where rn = 1 
관련 문제