【问题标题】:Run delete query until zero rows affected in postgresql运行删除查询,直到在 postgresql 中影响零行
【发布时间】:2013-05-29 20:22:06
【问题描述】:

我正在使用 PostGIS 处理一些复杂的土地利用数据。我有几个案例是创建了完全相同的多边形。我想删除这些重复项,我目前正在使用以下自联接 SQL 来删除重复项:

delete from landusetable where objectid in 
(select max(x.objectid) from landusetable x JOIN landusetable y ON 
ST_Equals(x.shape, y.shape) WHERE x.objectid <> y.objectid group by x.shape);

这可以很好地删除具有较高 objectid 值的重复项,但它只会删除最高 objectid。如果有 3 个或更多重复多边形,我需要多次运行此语句,直到删除语句影响 0 行,然后我知道我已经删除了所有重复。

那么,使用 PL/pgSQL 函数或其他控制结构,如何多次运行上述语句,直到收到“DELETE 0”,然后退出?我查看了文档,但我找不到如何使用 PL/pgSQL 从上一个查询中接收受影响的行数。

如果您能提供任何帮助,我们将不胜感激!

【问题讨论】:

  • 我在 SQL Server 中用于删除重复行的技术是使用 CTE 与 ROW_NUMBER() 函数相结合。稍微谷歌搜索一下,该技术也应该在 postgresql 中工作,但我不确定。

标签: sql postgresql duplicates postgis


【解决方案1】:

您可以使用子查询将row_number() 合并到您的查询中:

delete from landusetable
    where objectid in (select x.objectid
                       from (select x.objectid,
                                    ROW_NUMBER() over (partition by x.shape order by objectId) as seqnum
                             from landusetable x JOIN
                                  landusetable y
                                  ON ST_Equals(x.shape, y.shape)
                             WHERE x.objectid <> y.objectid
                            ) xy
                       where seqnum > 1
                      )

当然,如果您愿意,也可以将子查询放入 CTE。

在这种情况下,使用“标准”SQL 会产生更简单的查询。这个版本使用where exists而不是in

delete from landusetable
    where exists (select 1
                  from landusetable lut2
                  where ST_Equals(lut2.shape, landusetable.shape) and
                        lut2.objectid > landusetable.objectid
                 )

【讨论】:

    猜你喜欢
    • 2015-10-04
    • 2014-11-17
    • 1970-01-01
    • 2012-04-27
    • 1970-01-01
    • 1970-01-01
    • 2017-07-28
    • 2014-04-08
    相关资源
    最近更新 更多