删除日期不是最小值的行

Posted

技术标签:

【中文标题】删除日期不是最小值的行【英文标题】:Delete rows where date is not minimum 【发布时间】:2021-12-23 10:37:13 【问题描述】:

我有一个表(结构如下),我需要通过删除每个 Object_ID 的行来清理它:

WHERE Current_Step is NULL and Change = 'change' 
and Date_of_Change <> MIN(Date_of_Change)

也就是说,我只需要为每个Object_ID 留下具有最​​短日期的行。

表格示例

Object_ID Current_Step Change Date_of_Change
0025307 NULL change 16.11.2021
0025307 NULL change 19.11.2021
0025307 NULL change 19.11.2021

我正在使用 MS SQL。 没有主键。 所有列都是VARCHAR,除了Date_of_ChangeDATE 类型。

我需要清理此表的原因是因为源查询正在检查 IF NULL = NULL 然后将这些状态更改标记为已更改,即使它们没有更改,它也被错误地填充。所以我需要将值恢复到它们被更改的原始日期,因为如果它们仍然具有 NULL 值,则意味着状态没有发生实际变化。

期望的行为

我尝试识别需要保留的行:

SELECT [Object_ID]
      ,MIN([Date_of_Change])
FROM table
WHERE [Current_Step] IS NULL 
AND [Change] = 'change'
GROUP BY Object_ID

我只需要删除具有相同 Object_ID 且 Date_of_Change 不等于上述查询中标识的其他行。

【问题讨论】:

【参考方案1】:

像我在下面的“Table1223”上一样加入同一张桌子。

例子:

DELETE tbl 
FROM Table1223 tbl
JOIN (SELECT * FROM Table1223) objID
    ON objID.Object_ID = tbl.Object_ID
WHERE tbl.Date_of_Change > objID.Date_of_Change

【讨论】:

【参考方案2】:

架构

因此,您有一个包含 版本化 对象的表,其中包含与该对象关联的更改记录以及一些详细信息和日期。

现在你要选择

每个对象的第一次更改 最早的(在此对象更改的 GROUP 内) 在DATE 列类型上使用MIN 函数

这个最旧的应该被保留/保留并留下。应删除所有其他对象更改版本。

解决

A.分两步选择每个对象的第一个/最旧的更改。

    选择每个对象的 MIN(日期):
SELECT Object_ID, COUNT(Object_ID) AS Count_Changes, MIN(Date_of_Change) AS First_Change
FROM table
GROUP BY Object_ID

结果集包含每个对象的 total 更改计数和第一次更改的日期。

    JOIN 中使用subquery 之前的结果选择第一个更改:
SELECT *
FROM table t
-- join with a table-subquery having only 2 columns to correlate
JOIN ( 
  SELECT Object_ID, MIN(Date_of_Change) AS First_Change
  FROM table
  WHERE Current_Step is NULL and Change = 'change'
  GROUP BY Object_ID
) m ON t.Object_ID = m.Object_ID AND t.Date_of_Change = m.First_Change
WHERE Current_Step is NULL and Change = 'change'

这是要保留而不是删除的行。每个对象的第一次更改应该保留而不是清理。

B.现在我们可以反转 JOIN 条件来获取我们想要删除/清理的所有行:

    更改日期比较

) m ON t.Object_ID = m.Object_ID AND t.Date_of_Change = m.First_Change

不等于:

) m ON t.Object_ID = m.Object_ID AND t.Date_of_Change &lt;&gt; m.First_Change

    首先运行干选,至少在删除之前获得计数。
SELECT COUNT(Object_ID) AS records_to_remove
FROM table t
-- join with a table-subquery having only 2 columns to correlate
JOIN ( 
  SELECT Object_ID, MIN(Date_of_Change) AS First_Change
  FROM table
  WHERE Current_Step is NULL and Change = 'change'
  GROUP BY Object_ID
) m ON t.Object_ID = m.Object_ID AND t.Date_of_Change <> m.First_Change
WHERE Current_Step is NULL and Change = 'change'
    使用 JOIN 准备 DELETE 语句(如果 DBMS 支持):
DELETE FROM table t
JOIN ( 
  SELECT Object_ID, MIN(Date_of_Change) AS First_Change
  FROM table
  WHERE Current_Step is NULL and Change = 'change'
  GROUP BY Object_ID
) m ON t.Object_ID = m.Object_ID AND t.Date_of_Change <> m.First_Change
WHERE t.Current_Step is NULL AND t.Change = 'change'

替代 JOIN 在其他 DBMS 上尝试 USING

某些 DBMS 不支持在 DELETE 语句中加入 JOIN,但可以使用 USING 等替代方法:

DELETE FROM table t
USING ( 
  SELECT Object_ID, MIN(Date_of_Change) AS First_Change
  FROM table t2
  WHERE t2.Current_Step is NULL AND t2.Change = 'change'
) AS m
WHERE ...
AND t.Object_ID = m.Object_ID AND t.Date_of_Change <> m.First_Change

【讨论】:

感谢您的详尽解释。 MSSQL 的 USING 等价物是什么? 使用 DBMS 特定标签 sqlserver、postgresql 等搜索 [sql] DELETE with JOIN - 例如MS-SQL 允许JOIN in DELETE statements,PostgreSQL 有USING as JOIN-alternative for DELETE。

以上是关于删除日期不是最小值的行的主要内容,如果未能解决你的问题,请参考以下文章

删除/隐藏 UIDatePicker 最小/最大日期范围之外的行?

Python:返回矩阵中最小值的行索引

Pandas GroupBy 并选择特定列中具有最小值的行

在 Excel 中查找具有多种数据类型的行中的最小日期

在 numpy 数组中查找与所有其他行相比具有最小值的行

按列分组并选择具有多个最小值的行中的所有字段