Возвращение отдельного списка идентификаторов существования во всех подмножествах - PullRequest
3 голосов
/ 23 марта 2012

У меня есть две таблицы

Table "public.tags_to_entities"
 Column |  Type   | Modifiers 
--------+---------+-----------
 tid    | integer | not null
 eid    | integer | not null

   Table "public.tag_tree"
 Column |  Type   | Modifiers 
--------+---------+-----------
 tid    | integer | not null
 pid    | integer | not null
 level  | integer | 

tag_tree содержит все отношения между тегами, что означает, что SELECT pid FROM tag_tree WHERE tid = ? вернет родителей этого тега. Столбец level есть или только ORDER BY.

Я хочу вернуть список всех eid, которые имеют хотя бы один тег в каждом подмножестве тегов. Выполнение одного подмножества работает с использованием следующего запроса

SELECT DISTINCT eid
FROM tags_to_entities
WHERE
    tags_to_entities.tid = 1 OR
    tags_to_entities.tid IN (SELECT tag_tree.tid FROM tag_tree WHERE tag_tree.pid = 1));

Возвращает все eid, существующие в теге 1 или в одном из его дочерних тегов. Если я хочу вернуть все eid, существующие хотя бы в одном из тегов, связанных с 1 и 2. Мой неудачный подход пока

SELECT DISTINCT eid
FROM tags_to_entities
WHERE
    (
        tags_to_entities.tid = 1 OR
        tags_to_entities.tid IN (SELECT tag_tree.tid FROM tag_tree WHERE tag_tree.pid = 1)) AND
    (
        tags_to_entities.tid = 2 OR
        tags_to_entities.tid IN (SELECT tag_tree.tid FROM tag_tree WHERE tag_tree.pid = 2));

Это не сработает, поскольку tid не может быть одновременно 1 и 2. Как я могу решить это? (Ид будет объединен с таблицей записей позже)

1 Ответ

1 голос
/ 23 марта 2012

Вам нужно использовать GROUP BY вместо DISTINCT. Это позволяет использовать агрегатные функции и предложение HAVING.

SELECT
  map.eid
FROM
  tags_to_entities    AS map
INNER JOIN
  tag_tree            AS tree
    ON map.tid = tree.tid
WHERE
     (tree.tid = 1 OR tree.pid = 1)
  OR (tree.tid = 2 OR tree.pid = 2)
GROUP BY
  map.id
HAVING
  COUNT(DISTINCT CASE WHEN (tree.tid = 1 OR tree.pid = 1) THEN 1
                      WHEN (tree.tid = 2 OR tree.pid = 2) THEN 2
                 END)
  = 2

В предложениях JOIN и WHERE получают все сущности, у которых есть тег 1 или 2. Но затем вы объединяете их вместе, а затем подсчитываете, в скольких категориях находятся эти теги. Только если это 2, сущность проходит через предложение HAVING.

...