【问题标题】:Keep only rows where one column is minimal只保留一列最少的行
【发布时间】:2020-12-12 08:03:12
【问题描述】:

我正在寻找一个 SQLite 查询来大大减少我的数据库中不相关的噪音。 相关表包含点对('hexbin's),以及它们之间的距离和给出这个距离的源。对于每对点,我只想保留在任何源中找到的最小距离的行。

我认为

DELETE FROM dist
  WHERE hexbin1, hexbin2, source NOT IN (
    SELECT hexbin1, hexbin2, source FROM dist INNER JOIN (
      SELECT hexbin1 as h1, hexbin2 as h2, min(distance) as m
      FROM dist GROUP BY hexbin1, hexbin2)
    ON hexbin1==h1 AND hexbin2==h2 AND distance==m);

应该做大致正确的事情。 理论上,我可以有不同的行,它们具有相同的 hexbin1、hexbin2 和距离,但来源不同。在实践中,这不太可能也不会妨碍下一个需要使用数据库的流程,因此可以保留或删除它们,这取决于哪个更容易做;我上面的查询保留了重复项,但在其他条件相同的情况下,我宁愿只保留所有距离最短的样本中的任意样本。

天真地阅读,它在表格上迭代了 3 次,听起来很不方便。我怎样才能做得更好?

【问题讨论】:

  • hexbin1、hexbin2 的组合是否存在重复距离,因此最小距离存在于 1 行以上的情况?
  • 理论上,我可以有不同的行,它们具有相同的 hexbin1、hexbin2 和距离,但来源不同。在实践中,这不太可能并且不会妨碍需要使用数据库的下一个流程,因此可以根据哪个更容易操作来保留或删除它们。

标签: sql sqlite join sql-delete


【解决方案1】:

这个查询:

SELECT hexbin1, hexbin2, MIN(distance)
FROM dist d
GROUP BY hexbin1, hexbin2

返回hexbin1, hexbin2 的每个组合的所有最小距离。
如果没有重复最小距离的情况,您可以像这样使用它:

DELETE FROM dist
WHERE (hexbin1, hexbin2, distance) NOT IN (
  SELECT hexbin1, hexbin2, MIN(distance)
  FROM dist 
  GROUP BY hexbin1, hexbin2
)

查看简化的demo

但是如果有重复,那么在FIRST_VALUE()窗口函数的帮助下,决胜局可以是rowid列:

DELETE FROM dist
WHERE rowid NOT IN (
  SELECT FIRST_VALUE(rowid) OVER (PARTITION BY hexbin1, hexbin2 ORDER BY distance, rowid)
  FROM dist
)

查看简化的demo

【讨论】:

    【解决方案2】:

    你可以试试:

    delete from dist
        where exists (select 1
                      from dest d2
                      where d2.hexbin1 = d.hexbin1 and d2.hexbin2 = d.hexbin2 and d2.distance > d.distance
                     );
    

    特别是,这可以利用(hexbin1, hexbin2, distance) 上的索引。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2020-06-11
      • 1970-01-01
      • 1970-01-01
      • 2020-09-01
      • 1970-01-01
      • 2016-11-11
      • 2017-10-23
      • 2019-02-19
      相关资源
      最近更新 更多