Postgres在选择中跳过重复字段

时间:2018-01-08 02:00:43

标签: sql postgresql

我想选择有限数量的项目,但只保留具有特定字段的不同值的项目。我曾尝试使用SELECT DISTINCT ON(field)以及GROUP BY但它们都非常慢,因为表非常大。我假设这是因为使用DISTINCT实际上会在选择之前将表排序为不同的值。

SELECT DISTINCT ON(parent) id FROM posts WHERE sub = ? LIMIT 25

出于我的目的,这是不必要的,因为我使用LIMIT并且可以保证在不扫描大部分表的情况下将满足限制。与选择具有条件的值类似,其中(没有索引)将扫描每一行并在继续之前检查它是否满足条件,如何使用不具有重复字段作为条件?

另一种思考方式是如何做到这一点:

SELECT DISTINCT ON (parent) post.id FROM
(SELECT id FROM posts WHERE sub = ? ORDER BY id LIMIT 25) AS post

同时保证有25个结果。这里的结果非常快,但结果通常会少于所需的结果,因为多行可以具有相同的parent

2 个答案:

答案 0 :(得分:1)

你的思维方式似乎有道理,但如果你想得更深一点,你会发现它不能那样运作。你想要25个独特的结果。为此,首先需要查看记录并找到唯一的记录然后返回前25个。

你真正想要的是让它逐一浏览记录并检查,我是否已经有类似的价值?如果是,请丢弃并继续,如果不是,请将其添加到结果中。现在检查,我已经有25个结果吗?如果不是,请继续,如果是,则停止并返回结果。

在查询中,这不是一项简单的任务。最好的办法是在带光标的存储过程中执行此操作。当您完全控制流程时,这将更加容易,只需按照上述说明执行步骤。

  

就我的目的而言,这是不必要的,因为我使用LIMIT并且可以保证在不扫描大部分表格的情况下满足限制。

如果你真的知道你的前25个结果会在第一个xx记录中找到(比如前100个),并且你想要达到的只是那个,那么你可以使用一个有点愚蠢的查询:

SELECT DISTINCT ON (parent) post.id
FROM (SELECT id FROM posts WHERE sub = ? ORDER BY id LIMIT 100) AS post
LIMIT 25

将100更改为适合您需要的任何内容。

答案 1 :(得分:0)

使用distinct on时,您应该使用order by

SELECT DISTINCT ON (parent) id
FROM posts
WHERE sub = ?
ORDER BY parent
LIMIT 25;

要优化此查询,您需要posts(sub, parent, id)上的索引。