Запросы с произвольным логическим выражением в таблице соединений - PullRequest
0 голосов
/ 27 сентября 2018

Я пытаюсь смоделировать отношения «многие ко многим» между таблицами item и tag.Для этого у меня есть таблица соединений tagitemjoin.Например:

 id | tag_id | item_id
-----------------------
  1 |    1   |    1
  2 |    2   |    1
  3 |    2   |    2
  4 |    3   |    1
  5 |    3   |    2
  6 |    3   |    3
  7 |    4   |    2
  8 |    4   |    3
  9 |    5   |    3

, который представляет следующие соединения

       | item: 1 | item: 2 | item: 3
-------------------------------------
tag: 1 |    *    |         |
tag: 2 |    *    |    *    |
tag: 3 |    *    |    *    |    *
tag: 4 |         |    *    |    *
tag: 5 |         |         |    *

Я хочу запросить список item s на основе произвольных логических выражений, включающих, например, tag s:

tag1 OR ((NOT tag2) AND tag3)

Поскольку мне нужно реализовать 3 основных оператора, я смог реализовать OR следующим образом:

SELECT i.* FROM item i
           INNER JOIN tagitemjoin j
           ON (j.item_id = i.id)
           WHERE (j.tag_id = 3) OR (j.tag_id = 4) GROUP BY i.id

, и я уверен, что я также могу реализоватьОператоры NOT и AND каким-то образом используют COUNT.Однако ...

Как расширить это определение, чтобы иметь возможность обрабатывать произвольные логические выражения?Это то, что возможно с помощью этого метода таблицы соединений?

Если нет, я, вероятно, буду использовать подход NoSQL для сохранения tag s как набора в самих словарях item s, поскольку этот метод более прост.

Ответы [ 2 ]

0 голосов
/ 27 сентября 2018

Замена объединения подзапросами позволяет писать логическое выражение более естественным образом:

WITH tag1 AS (SELECT item_id FROM tagitemjoin WHERE tag_id = 1),
     tag2 AS (SELECT item_id FROM tagitemjoin WHERE tag_id = 2),
     tag3 AS (SELECT item_id FROM tagitemjoin WHERE tag_id = 3)
SELECT * FROM item
WHERE id IN tag1 OR (id NOT IN tag2 AND id IN tag3);
0 голосов
/ 27 сентября 2018

Мне нравятся group by и having для этого.Например, для тегов 3 или 4:

select tij.item_id
from tagitemjoin tij
group by tij.item_id
having sum(case when tij.tag_id = 3 then 1 else 0 end) > 0 or
       sum(case when tij.tag_id = 4 then 1 else 0 end) > 0;

sum(case . . . ) подсчитывает количество элементов, на которых появляется тег.Затем условие использует > 0, чтобы сказать, что тег существует;= 0 будет использоваться для указания того, что тег не существует.

Этот кадр достаточно обобщаем.Может использоваться для любой логической комбинации тегов.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...