删除日期不是最小值的行
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_Change
是DATE
类型。
我需要清理此表的原因是因为源查询正在检查 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 <> 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。以上是关于删除日期不是最小值的行的主要内容,如果未能解决你的问题,请参考以下文章