Понимание DISTINCT против DISTINCT ON против группы по - PullRequest
1 голос
/ 02 мая 2020

У меня есть запрос, который возвращает набор «записей». Результат всегда из одной таблицы и всегда должен быть уникальным. Он имеет набор внутренних объединений для фильтрации строк до соответствующего подмножества. Запрос возвращает примерно 10 столбцов. Однако я обнаружил, что он возвращал дублирующиеся строки, поэтому я добавил в запрос выборочный файл, который решил проблему с дублированием, но имеет существенные проблемы с производительностью.

Насколько я понимаю, 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.

1 Ответ

0 голосов
/ 02 мая 2020

Поскольку вы выбираете только из 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
        )
        ;
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...