首页 > 解决方案 > 了解 DISTINCT vs DISTINCT ON vs Group by

问题描述

我有一个返回一组“记录”的查询。结果始终来自同一个表,并且应该始终是唯一的。它有一组内部连接,用于将行过滤到适当的子集。该查询返回大约 10 列。但是,我发现它返回了重复的行,所以我在查询中添加了 select distinct,这解决了重复问题,但存在显着的性能问题。

我的理解是select distinct on (records.id), id...在这种情况下将返回相同的结果,因为所有重复项都将具有相同的主键,并且似乎快两倍。

我的其他测试表明它group by records.id再次更快,并且似乎做同样的事情?

我是否正确,所有这三种方法都将始终返回同一组单表记录?

此外,是否有一种简单的方法来比较不同方法的结果以确保返回集合?

这是我的查询:

  SELECT DISTINCT records.*
  FROM records
  INNER JOIN records parents on parents.path @> records.path
  INNER JOIN record_types ON record_types.id = records.record_type_id
  INNER JOIN user_roles ON user_roles.record_id = parents.id AND user_roles.user_id = _user_id
  INNER JOIN memberships ON memberships.role_id = user_roles.role_id
  INNER JOIN roles ON roles.id = memberships.role_id
  INNER JOIN groups ON memberships.group_id = groups.id AND
                              groups.id = record_types.view_group_id

任何单独的记录都可以有“父”记录树。这是使用 ltree 插件完成的。实际上,我们正在查看用户是否具有位于组中的角色,该组被定义为当前记录或任何父母的“查看组”。查询其实是一个函数,传入的是_user_id。

标签: databasepostgresql

解决方案


由于您只选择 from records,因此您不需要 DISTINCT; 记录已经不同了(我想)。

因此,您遇到的重复项可能是由所有联接引起的,例如,如果多个角色或组成员资格与您的一条记录匹配,则这些引用record中的每一个都将相同。


 SELECT *
  FROM records r
  WHERE EXISTS (
        SELECT *
        FROM records pa on pa.path @> r.path
         JOIN record_types typ ON typ.id = r.record_type_id
         JOIN user_roles ur ON ur.record_id = pa.id AND ur.user_id = _user_id
         JOIN memberships mem ON mem.role_id = ur.role_id
         JOIN roles ON roles.id = mem.role_id
         JOIN groups gr ON mem.group_id = gr.id AND gr.id = typ.view_group_id
        )
        ;

推荐阅读