SQL查询根据类型和日期排除记录

时间:2013-08-02 03:20:04

标签: sql-server sql-server-2008 tsql

ORIGINAL

 match_date actual_date      colA        type   type_desc
 09/16/11   10/1/2011        ABC12345    A      TTT222
 09/16/11   10/8/2011        ABC12345    S      BADTYPE_123
 09/16/11   11/8/2011        ABC12345    A      YYY222
 09/16/11   11/8/2011        ABC12345    A      WWW333
 09/16/11   11/8/2011        ABC12345    B      YYY222
 09/16/11   11/8/2011        ABC12345    B      WWW333   
 05/11/12   9/17/2012        ABC12345    B      ZZZ222
 05/11/12   9/17/2012        ABC12345    A      ZZZ222
 05/11/12   9/17/2012        MNO12345    B      CCC222
 05/11/12   9/17/2012        MNO12345    A      CCC222
 08/16/12   10/8/2011        MNO12345    S      BADTYPE_789
 08/16/12   10/9/2011        MNO12345    A      CCC111
 11/11/12   11/17/2012       MNO12345    S      BADTYPE_790
 12/01/12   9/17/2012        MNO12345    A      DDD222
 11/20/12   1/06/2013        XYZ98765    B      TST111
 11/20/12   1/06/2013        XYZ98765    A      TST111
 01/15/13   3/17/2013        XYZ98765    A      TST222
 05/11/13   6/15/2013        XYZ98765    B      TST111
 05/11/13   9/15/2013        XYZ98765    A      TST111

对于每个给定的match_date“组”(colA和匹配日期,ABC12345和09/16/11以及ABC12345 05/11/12在第一个“组”示例中),如果记录是“S”类型并包含“BADTYPE” *“作为type_desc,我想排除/删除给定”match_date组“的”BADTYPE“actual_date和下一个match_date之间的所有记录。

如果给定的“match_date组”没有“BADTYPE”记录,则应忽略该记录。如果给定match_date组的唯一记录是BADTYPE记录,则它将保留并继续。

要删除的记录

 match_date actual_date      colA        type   type_desc
 09/16/11   11/8/2011        ABC12345    A      YYY222
 09/16/11   11/8/2011        ABC12345    A      WWW333
 09/16/11   11/8/2011        ABC12345    B      YYY222
 09/16/11   11/8/2011        ABC12345    B      WWW333   
 08/16/12   10/9/2011        MNO12345    A      CCC111

删除记录的最终结果

 match_date actual_date      colA        type   type_desc
 09/16/11   10/1/2011        ABC12345    A      TTT222
 09/16/11   10/8/2011        ABC12345    S      BADTYPE_123  
 05/11/12   9/17/2012        ABC12345    B      ZZZ222
 05/11/12   9/17/2012        ABC12345    A      ZZZ222
 05/11/12   9/17/2012        MNO12345    B      CCC222
 05/11/12   9/17/2012        MNO12345    A      CCC222
 08/16/12   10/8/2011        MNO12345    S      BADTYPE_789
 11/11/12   11/17/2012       MNO12345    S      BADTYPE_790
 12/01/12   9/17/2012        MNO12345    A      DDD222
 11/20/12   1/06/2013        XYZ98765    B      TST111
 11/20/12   1/06/2013        XYZ98765    A      TST111
 01/15/13   3/17/2013        XYZ98765    A      TST222
 05/11/13   6/15/2013        XYZ98765    B      TST111
 05/11/13   9/15/2013        XYZ98765    A      TST111

希望我已经完全说明了我正在尝试做的事情。

非常感谢任何帮助。

2 个答案:

答案 0 :(得分:0)

我建议您使用递归查询。
像这样:

SELECT *, 
       Row_number() 
         OVER ( 
           PARTITION BY COLA, MATCH_DATE 
           ORDER BY ACTUAL_DATE) RN 
INTO   #TEMP1 
FROM   TABLE1; 

WITH CTE 
     AS (SELECT *, 
                Cast(1 AS INT) AS flag 
         FROM   #TEMP1 
         WHERE  RN = 1 
         UNION ALL 
         SELECT t1.*, 
                CASE 
                  WHEN T2.FLAG = 2 
                        OR ( t2.TYPE_DESC LIKE 'BADTYPE%' 
                             AND t2.TYPE = 'S' ) THEN 2 
                  ELSE 1 
                END flag 
         FROM   #TEMP1 T1 
                INNER JOIN CTE T2 
                        ON T1.COLA = T2.COLA 
                           AND t1.MATCH_DATE = t2.MATCH_DATE 
                           AND t1.RN = T2.RN + 1) 
SELECT [MATCH_DATE], 
       [ACTUAL_DATE], 
       [COLA], 
       [TYPE], 
       [TYPE_DESC] 
FROM   CTE 
WHERE  FLAG = 1 
ORDER  BY COLA, 
          MATCH_DATE 

您可以在SQL Fiddle上使用工作示例。

祝你好运!

答案 1 :(得分:0)

我认为最简单,最快捷的方法是使用窗口函数LEAD and LAG,但就您使用SQL Server 2008而言,这是不可能的。

在SQL Server 2008,您可以使用outer apply - 基本上您需要的是获取由actual_date降序排列的给定“match_group”的先前记录并删除记录(如果之前的type_desc like 'BADTYPE%' and type = 'S'}

当您决定需要什么时,您可以很容易地将该算法转录为SQL,并感受到声明性语言的强大功能:

delete Table1
from Table1 as T1
    cross apply
    (
        select top 1 T2.[type_desc], T2.[type]
        from Table1 as T2
        where T2.ColA = T1.ColA and T2.match_date = T1.match_date and T2.[actual_date] < T1.[actual_date]
        order by T2.[actual_date] desc
    ) as PR
where PR.[type_desc] like 'BADTYPE%' and PR.[type] = 'S'

您还可以查看SQL FIDDLE EXAMPLE以查看其工作原理