2

说,我有一个这样的表(SQL Server 2008):

CREATE TABLE tbl (ID INT, dtIn DATETIME2, dtOut DATETIME2, Type INT)

INSERT tbl VALUES
(1, '05:00', '6:00', 1),  -- will be removed
(2, '05:00', '7:00', 1),  -- will be removed
(3, '05:01', '8:00', 1),
(4, '05:00', '8:00', 1),
(5, '05:00', '6:00', 2),  -- will be removed
(6, '05:00', '7:00', 2),
(7, '05:00', '7:00', 3),
(8, '04:00', '7:00', 3)

我需要删除具有相同“类型”的相同“类型”(如果找到 2 个或更多)的所有记录,但具有最大“dtOut”的记录除外。换句话说,上表应该是这样的:

(3, '05:01', '8:00', 1),   -- no matching 'dtIn' for 'type' = 1
(4, '05:00', '8:00', 1),   -- largest 'dtOut' for 'type' = 1
(6, '05:00', '7:00', 2),   -- largest 'dtOut' for 'type' = 2
(7, '05:00', '7:00', 3),   -- no matching 'dtIn' for 'type' = 3
(8, '04:00', '7:00', 3)    -- no matching 'dtIn' for 'type' = 4

您甚至如何从同一个表中选择多个具有相同类型的行。你不能 select * from tbl where type=type.... 无论如何,我会很感激这方面的帮助...

4

5 回答 5

7

这是选择要删除的行的一种方法:

SELECT *
FROM tbl T1
WHERE EXISTS
(
    SELECT *
    FROM tbl T2
    WHERE T1.Type = T2.Type
    AND T1.dtIn = T2.dtIn
    AND (
            T1.dtOut < T2.dtOut
            OR (T1.dtOut = T2.dtOut AND T1.id < T2.id)
        )
)

此查询也可以轻松更改为实际删除行。只需更改SELECT *DELETE T1. 但请在实际运行删除语句之前测试它是否符合您的要求。

在线查看它:sqlfiddle


更新

这是使用 ROW_NUMBER 的方法:

;WITH T1 AS (
    SELECT id, ROW_NUMBER() OVER (PARTITION BY Type, dtIn
                                  ORDER BY dtOut DESC, ID DESC) AS rn
    FROM tbl
)
SELECT * FROM tbl
WHERE id IN
(
    SELECT id
    FROM T1
    WHERE rn > 1
)

在线查看它:sqlfiddle

于 2012-07-20T22:06:18.690 回答
1

不是很优雅(+条件与马克的答案相同),但它是另一种选择。

小提琴在这里

;with my_cte(ID)
as
(
  SELECT T1.ID
  FROM 
      tbl T1
      JOIN tbl T2 on
        T1.Type = T2.Type
        AND T1.dtIn = T2.dtIn
        AND T1.dtOut < T2.dtOut
  )
select *
from tbl t
where not exists 
              (
              select 1 
              from my_cte c 
              where t.ID = c.ID
              ) 
于 2012-07-20T22:41:22.807 回答
1

重复行的查询

我刚刚看到你可以有重复的行。所以:

DELETE X
FROM
   (SELECT Row_Number() OVER (PARTITION BY Type, dtIn ORDER BY dtOut DESC) Item, *
   FROM #tbl) X
WHERE Item > 1

请注意,上面的这个版本不需要连接,因此应该比页面上的所有其他查询执行得更好。

或者

DELETE T
FROM #tbl T
   CROSS APPLY (
      SELECT TOP 1 *
      FROM #tbl T2
      WHERE
         T.dtIn = T2.dtIn
         AND T.Type = T2.Type
      ORDER BY T2.dtOut DESC, T2.ID DESC
   ) X
WHERE T.ID < X.ID

或者

DELETE T
FROM #tbl T
   INNER JOIN #tbl T2
      ON T.dtIn = T2.dtIn
      AND T.Type = T2.Type
      AND (
         T.dtOut < T2.dtOut
         OR (T.tdOut = T2.dtOut AND T.ID > T2.ID)
      )

查询无重复行

如果您不能有重复的行(ID 除外),那么它会更简单:

DELETE T
FROM #tbl T
WHERE EXISTS (
   SELECT * FROM #tbl T2
   WHERE
      T.dtIn = T2.dtIn
      AND T.Type = T2.Type
      AND T.dtOut < T2.dtOut
)

甚至

DELETE T
FROM #tbl T
   INNER JOIN #tbl T2
      ON T.dtIn = T2.dtIn
      AND T.Type = T2.Type
      AND T.dtOut < T2.dtOut
于 2012-07-20T23:37:19.120 回答
0
DECLARE @Table TABLE     
(  
ID INT,  
newno int  
)   

insert @table  
SELECT T1.ID,   
ROW_NUMBER() OVER (PARTITION BY Type, dtIn
                              ORDER BY dtOut DESC, ID DESC) AS newno  
 FROM tbl T1      

 select *  
from tbl t
where t.ID IN
             (
              select ID from @Table where newno > 1
              )    
于 2012-07-21T00:00:17.463 回答
0

我的与@Mark 的有点不同,但我相信它应该会得到相同的结果(只是因为我认为这id是独一无二的):

DELETE a
FROM dbo.tbl a
WHERE id <> (
    SELECT MAX(id)
    from dbo.tbl b
    WHERE a.type = b.type
      AND a.dtIn = b.dtIn
)
于 2012-07-20T22:14:47.263 回答