【问题标题】:Delete redundant SQL Server rows删除多余的 SQL Server 行
【发布时间】:2023-03-25 14:19:01
【问题描述】:

我有 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).

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

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

例如我们在 Tracking 表中有以下 2 行:

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

我们在日期表中有以下 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_date、Place_ID、Label_ID)具有最小 date_id 的行。

谁能有最优化的解决方案?

谢谢

【问题讨论】:

  • 请注意:from Tracking since it is the row having the smallest date_id 你可能是指最大的 Date_ID
  • 是的,我想保留 Date_ID 最小的行,所以我删除了最大的行:D
  • @user3569267,我觉得你的评论是错误的。如果您有 3 条记录,那么确定最大的将无济于事。我认为我们应该找到最小值并根据它加入。
  • 我们可以不使用光标吗?如果是的话,你能告诉我如何(用 SQL 语法)吗?谢谢

标签: sql-server


【解决方案1】:

这是我的例子。

首先我收集坏了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

【讨论】:

    【解决方案2】:

    稍微不同的方法是直接从 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
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-01-15
      • 1970-01-01
      • 1970-01-01
      • 2023-03-04
      • 2011-05-24
      • 1970-01-01
      相关资源
      最近更新 更多