删除冗余的SQL Server行

时间:2014-05-28 13:24:54

标签: sql-server

我有2个SQL Server表:日期和跟踪。 在第一个表(日期)中,我们只有2列

(fields):
Date_ID (int primary key) 
Date_Date (datetime).

在第二个(跟踪)中,我们有4列:

-Tracking_ID (int primary key)
-Date_ID (int foreign key)
-Place_ID (int foreign key)
-Label_ID (int foreign key).

跟踪的主键是三元组(Date_ID,Place_ID,Label_ID)

我想从Tracking表中删除具有相同date_date但具有不同date_id的行,以及相同的Place_ID和Label_ID 我想保留具有最小Date_ID的行。

例如,我们在跟踪表中有以下两行:

row1: Tracking_ID=1;Date_ID=109;Place_ID=55;Label_ID=40
row2: Tracking_ID=2;Date_ID=110;Place_ID=55;Label_ID=40

我们在表Date中有以下2行:

row1: Date_ID=109; Date_Date=2014-05-28 00:00:00
row2: Date_ID=110; Date_Date=2014-05-28 00:00:00

我的目的是从Tracking中删除第2行,因为它是具有相同三元组的最小date_id的行(date_date,Place_ID,Label_ID)。

任何人都可以拥有最优化的解决方案吗?

由于

2 个答案:

答案 0 :(得分:0)

这是我的例子。

首先我收集了不好的Tracking_IDs 然后我删除它们。

DECLARE @Date TABLE(
    Date_ID int,
    Date_Date datetime
)

DECLARE @Tracking TABLE(
    Tracking_ID int,
    Date_ID int,
    Place_ID int,
    Label_ID int
)

DECLARE @ForDelete TABLE(
    Tracking_ID int
)

INSERT INTO @Date SELECT 109,'2014-05-28 00:00:00'
INSERT INTO @Date SELECT 110,'2014-05-28 00:00:00'
INSERT INTO @Date SELECT 111,'2014-05-29 00:00:00'
INSERT INTO @Date SELECT 112,'2014-05-29 00:00:00'
INSERT INTO @Date SELECT 113,'2014-05-29 00:00:00'

INSERT INTO @Tracking SELECT 1, 109, 55, 40
INSERT INTO @Tracking SELECT 2, 110, 55, 40
INSERT INTO @Tracking SELECT 3, 110, 56, 40
INSERT INTO @Tracking SELECT 4, 111, 55, 40
INSERT INTO @Tracking SELECT 5, 111, 55, 40
INSERT INTO @Tracking SELECT 6, 112, 57, 40
INSERT INTO @Tracking SELECT 7, 111, 57, 40
INSERT INTO @Tracking SELECT 8, 113, 57, 40

;WITH test AS (
SELECT T.Tracking_ID, T.Date_ID, T.Place_ID, T.Label_ID, D.Date_Date
FROM @Tracking AS T
INNER JOIN @Date AS D
    ON T.Date_ID = D.Date_ID
)
INSERT INTO @ForDelete
SELECT DISTINCT t1.Tracking_ID
FROM test as t1
INNER JOIN test as t2
    ON t1.Date_Date = t2.Date_Date
    AND t1.Place_ID = t2.Place_ID
    AND t1.Label_ID = t2.Label_ID
    AND t1.Date_ID > t2.Date_ID

DELETE FROM T
FROM @Tracking AS T
INNER JOIN @ForDelete AS FD
    ON FD.Tracking_ID = T.Tracking_ID

SELECT *
FROM @Tracking

答案 1 :(得分:0)

稍微不同的方法是直接从cte中删除而不是将其放入临时删除表中:

;WITH cte AS (
SELECT D.Date_Date, T.Date_ID, T.Place_ID, T.Label_ID, ROW_NUMBER() OVER (PARTITION BY T.Place_ID, T.Label_ID ORDER BY T.Date_ID) AS RowNum
FROM  [Date] D
INNER JOIN Tracking T ON D.Date_ID = T.Date_ID)

DELETE T
FROM cte
INNER JOIN Tracking T ON cte.Date_ID = T.Date_ID AND cte.Place_ID = T.Place_ID AND cte.Label_ID = T.Label_ID
WHERE RowNum > 1