陷入了对t-SQL中单个表的选择性DELETE语句

ahm*_*md0 2 sql t-sql sql-server sql-delete

说,我有一个像这样的表(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)
Run Code Online (Sandbox Code Playgroud)

我需要删除相同'类型'的所有记录(如果找到2个或更多),使用相同的'dtIn'作为'type',除了具有最大'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
Run Code Online (Sandbox Code Playgroud)

你如何从同一个表中选择具有相同类型的多个行.你不能从tbl中选择*,其中type = type ....无论如何,我很感激对此有所帮助......

Mar*_*ers 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)
        )
)
Run Code Online (Sandbox Code Playgroud)

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

看到它在线工作: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
)
Run Code Online (Sandbox Code Playgroud)

看到它在线工作:sqlfiddle

  • @ ahmd0:很多练习!我第一次做这样的事情,我也花了很长时间.:-) (3认同)