基于相关MIN()和MAX()值的不同值

时间:2014-01-29 15:21:28

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

我有一个名为EVENTS的表,我需要编写4个脚本来生成4个不同EVENT_ID值的独立表。下面是第一个脚本,另外3个将是类似的逻辑。任何人都可以帮助这个第一个脚本,所以我可以希望将其用作其他3个脚本的模板。我在SQL2005中编写这些脚本,它必须向后兼容SQL2000。我删除了任何重复项,因此不需要在逻辑中涉及EVENT_ID的等级。

  

对于每个CARE_ID,选择具有EVENT_TYPE的EVENT_ID的值   CP的并且具有MAX(EVENT_DATE),其中< = MIN(EVENT_DATE)其中   EVENT_TYPE位于('B','CH','S','T')

    CARE_ID    EVENT_ID     EVENT_DATE  EVENT_TYPE
    3          194          01/10/2012  S
    3          228          07/07/2010  S
    3          104          12/05/2010  CH
    3          16           12/07/2010  B
    3          17           13/07/2010  B
    3          43           15/01/2010  P
    3          189          15/04/2010  S
    39         45           09/10/2009  T
    39         4            21/07/2009  P
    39         6            21/07/2009  CH
    78         28           08/07/2009  S
    78         706          08/12/2010  CP
    78         707          09/12/2010  CP
    78         9            28/07/2009  T
    78         11           28/07/2009  CH
    95         21           31/07/2009  CH
    95         21           31/07/2009  T
    107        1474         21/09/2012  S
    107        93           23/02/2010  CP
    107        59           29/10/2012  P
    107        58           29/12/2009  P
    151        186          19/03/2010  S
    151        49           21/03/2010  T
    152        69           26/08/2009  CH
    206        85           21/08/2009  CP
    206        84           28/07/2009  CP
    217        158          18/02/2010  S
    217        102          30/03/2010  CH
    218        159          12/03/2010  S
    227        1378         01/04/2011  CP
    355        19           13/07/2010  B
    355        20           13/07/2010  B
    355        239          13/07/2010  S
    355        56           16/07/2010  T
    355        111          16/07/2010  CH
    364        1136         18/02/2011  CP
    364        569          19/02/2011  S
    364        774          23/08/2012  CH
    364        1122         26/01/2011  CP
    367        247          01/07/2010  S
    367        151          21/06/2010  CP
    369        108          26/07/2010  P
    369        152          27/07/2010  CP
    369        109          28/07/2010  P
    369        117          28/07/2010  CH
    369        248          28/07/2010  S
    380        277          08/07/2011  T
    396        1573         06/06/2011  CP
    481        63           07/09/2010  T
    481        116          07/09/2010  P
    481        194          07/09/2010  CP
    481        289          07/09/2010  S
    502        200          13/08/2010  CP
    530        220          14/06/2010  CP
    535        222          05/07/2010  CP
    535        303          13/07/2010  S
    535        223          19/07/2010  CP
    535        224          26/07/2010  CP
    536        135          10/09/2010  CH
    536        225          23/08/2010  CP
    568        155          06/10/2010  P
    568        315          15/10/2010  S
    631        148          02/02/2010  CH
    631        74           15/01/2010  T
    631        256          15/12/2009  CP
    631        345          15/12/2009  S
    631        147          25/12/2009  CH
    632        259          18/09/2010  CP
    653        189          29/10/2010  P
    653        360          30/09/2010  S
    655        1570         06/06/2011  CP
    680        569          08/12/2010  CP
    680        1191         24/11/2011  S
    680        530          25/01/2011  S
    680        151          30/09/2010  P
    680        281          30/09/2010  CP
    680        480          30/11/2010  CP
    689        306          02/11/2010  CP
    689        158          06/10/2010  P
    689        372          06/10/2010  S
    689        2720         06/11/2012  CP
    689        2736         11/11/2012  CP
    689        2752         13/11/2012  CP
    689        2765         15/11/2012  CP
    689        2125         22/09/2011  CP
    689        2654         24/09/2012  CP
    689        1944         26/08/2011  CP
    689        307          26/10/2010  CP
    689        1947         27/08/2011  CP
    729        299          15/09/2010  CP
    811        413          27/10/2010  S
    834        622          01/01/2012  CH
    834        1233         06/01/2012  S
    834        624          15/01/2012  CH
    834        625          23/01/2012  CH
    834        627          23/01/2012  CH
    838        629          02/01/2012  CH
    838        630          20/01/2012  CH
    838        632          27/01/2012  CH
    846        416          05/10/2010  S
    849        195          03/11/2010  P
    849        336          21/02/2011  CP
    923        441          26/07/2010  S
    963        371          29/10/2010  CP
    981        624          23/03/2011  S
    984        384          13/11/2010  CP
    984        392          18/11/2010  CP

2 个答案:

答案 0 :(得分:2)

尝试使用HAVING子句?也许我搞砸了一些东西,但是你的测试数据似乎只有一个这样的条目,即S案例,如下:

SELECT  e.[CARE_ID], e.[EVENT_ID]
FROM    dbo.EVENTS e
WHERE   e.[EVENT_TYPE] = 'CP'
GROUP BY e.[CARE_ID], e.[EVENT_ID]
HAVING  MAX( e.[EVENT_DATE] ) <= ( SELECT  MIN( [EVENT_DATE] )
                                   FROM    [EVENTS]
                                   WHERE   [EVENT_ID] = e.[EVENT_ID]
                                       AND [EVENT_TYPE] = 'S' );

这是一个SQL Fiddle来帮助你解决问题!

修改:原来的小提琴正在寻找EVENT_ID的最大日期,当我们应该查找CARE_ID的最大日期时。我认为this会让你走上正轨!

SELECT  e.[CARE_ID], e.[EVENT_ID]
FROM    dbo.EVENTS e
WHERE   e.[EVENT_TYPE] = 'CP'
GROUP BY e.[CARE_ID], e.[EVENT_ID]
HAVING  MAX( e.[EVENT_DATE] ) <= ( SELECT  MIN( [EVENT_DATE] )
                                   FROM    [EVENTS]
                                   WHERE   [CARE_ID] = e.[CARE_ID]
                                       AND [EVENT_TYPE] = 'S' );

编辑3 Now with proper DATETIME

编辑4 :区分EVENT_ID

SELECT DISTINCT e.[EVENT_ID]
FROM dbo.EVENTS e
WHERE e.[EVENT_TYPE] = 'CP'
GROUP BY e.[CARE_ID], e.[EVENT_ID]
HAVING MAX( e.[EVENT_DATE] ) <= ( SELECT MIN( [EVENT_DATE] )
                                 FROM dbo.[EVENTS]
                                 WHERE [CARE_ID] = e.[CARE_ID]
                                     AND [EVENT_TYPE] = 'S' );

答案 1 :(得分:1)

使用窗口函数直接转换为SQL:

select care_id, event_id
from (select e.*,
             max(case when event_type = 'CP' then event_date end) over (partition by care_id) as MaxED_CP,
             min(case when event_type = ('B','CH','S', 'T') then event_date end) over (partition by care_id) as MinED_others,
      from events e
     ) e
where event_type = 'CP' and
      MaxED_CP <= MinED_others and
      event_date = MaxED_CP;

这些函数计算每一行的max()min()值。外部查询只选择适当的行。

请注意,如果给定care_id不存在此类事件,则care_id不在输出中。

这不与SQL Server 2000向后兼容。如果它可以工作,那么你可以用子查询替换窗口函数。