Выберите все строки, которые имеют хотя бы список функций с поддержкой подстановочных знаков - PullRequest
0 голосов
/ 02 июня 2018

с учетом определения таблицы:

Objects:
 obj_id | obj_name
 -------|--------------
  1     | object1
  2     | object2
  3     | object3

Tags:
  tag_id | tag_name
  -------|--------------
   1     | code:python
   2     | code:cpp
   3     | color:green
   4     | colorful
   5     | image

objects_tags:
  obj_id | tag_id
  -------|---------
   1     | 1
   1     | 2
   2     | 1
   2     | 3
   3     | 1
   3     | 2
   3     | 3

Я бы хотел выбрать объекты, которые содержат все теги из данного списка с подстановочными знаками .Подобный вопрос задавался несколько раз, и ответ на более простой вариант выглядит примерно так:

SELECT obj_id,count(*) c FROM objects_tags
INNER JOIN objects USING(obj_id)    
INNER JOIN tags USING(tag_id)
WHERE (name GLOB 'code*' OR name GLOB 'color*')
GROUP BY obj_id
HAVING (c==2)

Однако это решение не работает с подстановочными знаками.Можно ли создать аналогичный запрос, который бы возвращал объекты, которые для каждого данного подстановочного запроса возвращали хотя бы 1 тег?Проверка, не работает ли c>=2, потому что один подстановочный тег может возвращать несколько результатов, в то время как другой может возвращать 0, все еще передавая запрос, даже если это не должно.из N INTERSECT s (по одному на тег), потому что их, вероятно, не будет много, но это звучит как очень грязное решение, и если есть еще какой-то способ SQL, я бы предпочел использовать его.

1 Ответ

0 голосов
/ 03 июня 2018

SQLite поддерживает предложение WITH , поэтому я постараюсь сначала использовать его для определения всех тегов, а затем использовать эти теги для поиска объектов следующим образом.

Пример ( demo ) создан для PostGreSQL, потому что я не смог запустить SQLIte на любом онлайн-тестере, но я верю, что вы легко конвертируете его в SQLite:


этот запрос извлекает все теги:

WITH tagss AS (
  SELECT * FROM Tags
  WHERE tag_name LIKE 'code:%' OR tag_name LIKE 'color:%'
)
SELECT * FROM tagss;

| tag_id |    tag_name |
|--------|-------------|
|      1 | code:python |
|      2 |    code:cpp |
|      3 | color:green |

и последний запрос использует вышеуказанный подзапрос следующим образом:

WITH tagss AS (
  SELECT * FROM Tags
  WHERE tag_name LIKE 'code:%' OR tag_name LIKE 'color:%'
)
SELECT obj_id,count(*) c 
FROM objects_tags
INNER JOIN tagss USING(tag_id)
WHERE tag_name IN ( SELECT tag_name FROM tagss) 
GROUP BY obj_id
HAVING count(*) >= (
    SELECT count(*) FROM tagss
)

| obj_id | c |
|--------|---|
|      3 | 3 |
...