【问题标题】:What script will return the required data?什么脚本会返回所需的数据?
【发布时间】:2014-05-07 12:13:10
【问题描述】:

我正在使用此脚本尝试从下表中检索符合此条件的行,但我认为它无法正常工作。 例如,对于 CARE_ID 3907,正在返回 EVENT_ID 3593 的行,我相信这应该是 3591。 该脚本必须相当老派才能与 SQL2000 兼容。

 SELECT nbe.CARE_ID, nbe.EVENT_DATE, nbe.EVENT_ID, nbe.EVENT_TYPE
   FROM vwNBOCAP_BASE_EVENTS nbe
        JOIN
            (SELECT CARE_ID, EVENT_TYPE, MAX(EVENT_DATE) as maxx
               FROM vwNBOCAP_BASE_EVENTS
              GROUP BY CARE_ID, EVENT_TYPE
             HAVING EVENT_TYPE = 'CP'
            ) tmax
            ON nbe.CARE_ID = tmax.CARE_ID AND nbe.EVENT_DATE = tmax.maxx
  WHERE nbe.EVENT_TYPE = 'CP'
    AND EVENT_DATE <= 
        (SELECT MIN(EVENT_DATE)
           FROM vwNBOCAP_BASE_EVENTS
          WHERE CARE_ID = nbe.CARE_ID
            AND EVENT_TYPE IN ('BR','CH','SU', 'TE'))

UNION ALL

 SELECT t.CARE_ID, t.EVENT_DATE, MAX(t.EVENT_ID) AS EVENT_ID, t.EVENT_TYPE
   FROM vwNBOCAP_BASE_EVENTS t
        JOIN 
            (SELECT CARE_ID, MAX(EVENT_DATE) as maxx, EVENT_TYPE
               FROM vwNBOCAP_BASE_EVENTS
              GROUP BY CARE_ID, EVENT_TYPE
             HAVING EVENT_TYPE = 'CP'
            ) tmax
            ON t.CARE_ID = tmax.CARE_ID AND t.EVENT_DATE = tmax.maxx
  GROUP BY t.CARE_ID, t.EVENT_DATE, t.EVENT_TYPE
 HAVING t.EVENT_TYPE = 'CP'
    AND t.CARE_ID NOT IN
        (SELECT CARE_ID
           FROM
                (SELECT nbe.CARE_ID, nbe.EVENT_DATE, MAX(nbe.EVENT_ID) AS EVENT_ID,
                        nbe.EVENT_TYPE
                   FROM vwNBOCAP_BASE_EVENTS nbe
                        JOIN
                            (SELECT CARE_ID, EVENT_TYPE, MAX(EVENT_DATE) as maxx
                               FROM vwNBOCAP_BASE_EVENTS
                              GROUP BY CARE_ID, EVENT_TYPE
                             HAVING EVENT_TYPE = 'CP') tmax
                            ON nbe.CARE_ID = tmax.CARE_ID AND nbe.EVENT_DATE = tmax.maxx
                  GROUP BY nbe.CARE_ID, nbe.EVENT_DATE, nbe.EVENT_TYPE
                 HAVING nbe.EVENT_TYPE = 'CP'
                    AND EVENT_DATE <=
                        (SELECT MIN(EVENT_DATE)
                           FROM vwNBOCAP_BASE_EVENTS
                          WHERE CARE_ID = nbe.CARE_ID
                            AND EVENT_TYPE IN ('BR','CH','SU','TE'))
                )a
        )

评论

--For each CARE_ID with at least one EVENT_TYPE of 'CP' before an 
--EVENT_TYPE of 'BR', 'CH', 'SU', 'TE' return the most recent instance 
--of 'CP' - i.e. the last CP before the first 'BR', 'CH', 'SU' or 'TE' 
--(the tie breaker for 'CP' is MAX(EVENT_ID) and MIN(EVENT_ID) 
--for 'BR', 'CH', 'SU' or 'TE')

--For each CARE_ID with at least one EVENT_TYPE of 'CP' 
--that isn't included above return the most recent 'CP' 
--(the tie breaker for 'CP' is MAX(EVENT_ID))

输出

CARE_ID EVENT_ID    EVENT_DATE          EVENT_TYPE
3       117         09/04/2010 00:00    CP
3       104         11/04/2010 00:00    CH
3       190         16/04/2010 00:00    SU
3       16          12/07/2010 00:00    BR
3       17          13/07/2010 00:00    BR
3       18          13/07/2010 00:00    BR
78      11          27/07/2009 00:00    CH
78      9           28/07/2009 00:00    TE
78      706         08/12/2010 00:00    CP
78      707         09/12/2010 00:00    CP
107     93          23/02/2010 00:00    CP
107     1474        21/09/2012 00:00    SU
206     84          28/07/2009 00:00    CP
206     85          21/08/2009 00:00    CP
364     1122        26/01/2011 00:00    CP
364     1136        18/02/2011 00:00    CP
364     569         19/02/2011 00:00    SU
364     774         23/08/2012 00:00    CH
367     151         21/06/2010 00:00    CP
367     247         01/07/2010 00:00    SU
369     248         26/07/2010 00:00    SU
369     152         27/07/2010 00:00    CP
369     117         28/07/2010 00:00    CH
380     277         08/07/2011 00:00    TE
481     63          07/09/2010 00:00    TE
481     194         07/09/2010 00:00    CP
481     289         07/09/2010 00:00    SU
1535    924         11/01/2011 00:00    CP
1536    925         11/01/2011 00:00    CP
1565    979         09/01/2011 00:00    CP
1623    531         27/01/2011 00:00    SU
1661    216         25/01/2011 00:00    CH
1661    217         25/01/2011 00:00    CH
1661    1046        25/01/2011 00:00    CP
1661    95          01/02/2011 00:00    TE
1661    218         01/02/2011 00:00    CH
1662    220         25/01/2011 00:00    CH
1662    1047        25/01/2011 00:00    CP
1662    221         01/02/2011 00:00    CH
1663    97          25/01/2011 00:00    TE
1663    1048        25/01/2011 00:00    CP
1663    98          01/02/2011 00:00    TE
1663    223         01/02/2011 00:00    CH
1665    1049        25/01/2011 00:00    CP
1666    100         23/01/2011 00:00    TE
1666    1050        23/01/2011 00:00    CP
1666    225         01/02/2011 00:00    CH
1781    1868        04/10/2010 00:00    CP
1781    1869        04/10/2010 00:00    CP
1781    1870        04/10/2010 00:00    CP
1781    1052        10/02/2011 00:00    SU
1781    1867        25/03/2011 00:00    CP
1781    2103        20/01/2014 00:00    CP
1903    1551        02/06/2011 00:00    CP
1903    1552        16/07/2011 00:00    CP
2187    1475        20/01/2011 00:00    CP
2187    803         29/01/2011 00:00    SU
2294    66          12/06/2011 00:00    BR
2294    1697        16/07/2011 00:00    CP
2294    1698        17/07/2011 00:00    CP
3907    3591        05/01/2014 00:00    CP
3907    945         09/01/2014 00:00    CH
3907    1821        13/01/2014 00:00    SU
3907    3592        14/01/2014 00:00    CP
3907    3593        14/01/2014 00:00    CP

【问题讨论】:

  • 此查询太大,乍一看无法确定错误,您可能最终没有答案。也许您应该简化查询和数据集以产生与您相似的结果。
  • 抱歉,这对我来说太复杂了,我无法通过阅读来理解。您可以使用sqlfiddle.com 进行复制吗?

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


【解决方案1】:

我的第一条评论退出 SQL Server 2000。 SQL Server 2014 的发布是在 1 个月前。然而,作为一名 DBA,我曾与未规划未来的业务线合作。他们想一直使用该软件,直到它无法支持为止。

我的第二条评论使用临时表来简化查询。虽然您可能无法将最终结果注入到软件中,但它会留下可用于调查和调试的跟踪表。

不要忘记,此代码可以包装在返回结果集的存储过程中。如果是报表,只需更改调用代码即可。

所以这是比上面简单得多的重写。

最大和最小查询有自己的表。我确实注意到最小事件类型标准与最大事件类型标准不同。

我在分组上添加了回事件类型。这可以通过另一个 MIN() 调用在子查询中消除。但是,为了保持一致性,有一些话要说。

--
-- Create temp table for max event date
--

SELECT 
    CARE_ID, 
    EVENT_TYPE, 
    MAX(EVENT_DATE) as maxx
INTO
    #tmax
FROM 
    vwNBOCAP_BASE_EVENTS
GROUP BY 
    CARE_ID, EVENT_TYPE
HAVING 
    EVENT_TYPE = 'CP'
GO


--
-- Create temp table for min event date
--

SELECT 
    CARE_ID, 
    EVENT_TYPE, 
    MIN(EVENT_DATE) as minn
INTO
    #tmin
FROM 
    vwNBOCAP_BASE_EVENTS
GROUP BY 
    CARE_ID, EVENT_TYPE
HAVING 
    EVENT_TYPE IN ('BR','CH','SU', 'TE')
GO

实际的核心查询现在更清晰了。我从 union all 的最后一个子查询中删除了分组,因为您只需要 CARE ID。

--
-- Actual query
-- 

SELECT  
    nbe.CARE_ID, 
    nbe.EVENT_DATE, 
    nbe.EVENT_ID, 
    nbe.EVENT_TYPE
FROM    
    vwNBOCAP_BASE_EVENTS nbe
JOIN 
    #tmax 
ON 
    nbe.CARE_ID = #tmax.CARE_ID AND 
    nbe.EVENT_DATE = #tmax.maxx
WHERE 
    nbe.EVENT_TYPE = 'CP' AND 
    EVENT_DATE <= 
    (SELECT MIN(#tmin.minn) FROM #tmin WHERE #tmin.CARE_ID = nbe.CARE_ID)


UNION ALL


SELECT  
    t.CARE_ID, 
    t.EVENT_DATE, 
    MAX(t.EVENT_ID) AS EVENT_ID, 
    t.EVENT_TYPE
FROM    
    vwNBOCAP_BASE_EVENTS t 
JOIN 
    #tmax 
ON 
    nbe.CARE_ID = #tmax.CARE_ID AND 
    nbe.EVENT_DATE = #tmax.maxx
GROUP BY 
    t.CARE_ID, 
    t.EVENT_DATE, 
    t.EVENT_TYPE
HAVING
    t.EVENT_TYPE = 'CP' AND
    t.CARE_ID NOT IN
(
SELECT 
    DISTINCT CARE_ID 
FROM    
    vwNBOCAP_BASE_EVENTS nbe
JOIN  
    #tmax
ON 
    nbe.CARE_ID = #tmax.CARE_ID 
    AND nbe.EVENT_DATE = #tmax.maxx
WHERE
    nbe.EVENT_TYPE = 'CP' AND 
    EVENT_DATE <= 
    (SELECT MIN(#tmin.minn) FROM #tmin WHERE #tmin.CARE_ID = nbe.CARE_ID)
)

再说一次,我不知道你的业务逻辑;但是,清理后的版本应该更容易调试。

我选择回答这个问题,因为我今晚要在美国缅因州发表演讲 - PASS SQL Server User Group on Effective Use of Temporary Tables。

这个问题正好适合我的主题。,

祝你好运,狡猾的 dba。

【讨论】:

  • 感谢您的意见。我在一家为仍在使用 Enterprise Manager 和 SQL2000 的客户提供应用程序和数据库的组织工作。谢天谢地,只剩下两个了,他们正在注意。我完全支持临时表,只要它们不会对数据库造成太大影响。我已经更正了您脚本中的一些假名以使其运行,但它没有返回预期的数据。 CARE_ID 3907 仍在返回 EVENT_ID 3593,它是最新的 EVENT_ID,而不是在第一个 'BR'、'CH'、'SU' 或 'TE' 实例之前的最新 EVENT_ID
  • 嗨,保罗,唯一的打击是 tempdb 中的空间。只需确保您至少有 4 个数据文件,每个文件 1 GB。我通常至少有一个 256 MB 的日志文件。默认值(来自模型)就像 8 mb 数据和 1 mb 日志。祝你好运 - J
猜你喜欢
  • 2014-07-02
  • 2015-04-19
  • 2021-04-13
  • 2021-03-21
  • 2016-02-17
  • 1970-01-01
  • 2014-02-08
  • 2018-07-06
  • 1970-01-01
相关资源
最近更新 更多