基于多列返回表

时间:2014-10-01 16:14:01

标签: sql sql-server tsql sql-server-2005

在下面的示例表中,我需要一个脚本,以便在第一个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

4 个答案:

答案 0 :(得分:1)

使用ROW_NUMBER()的示例,SQL Server 2005支持:

[编辑:如果您的真实数据集的情况下某些person_id没有S类型或者某些person_id的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的Lead函数根据您要分区和排序这些分区的每一行获取下一行的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 :(得分:0)

您可以使用not exists在第一个CPS之前选择所有row_number(),以选择这些行的最后CP个(即最后一个CP第一个S之前的{1}}

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 :(得分: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

答案 3 :(得分:0)

与except语句的联合返回所有必需的行 - 甚至是在S的第一个实例之前和之后都具有CP实例的行。 我确信必须有一个比这更有效的解决方案,但时间和资源目前不是我的同伴!

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