Условия выбора отношений «многие ко многим» MySQL - PullRequest
0 голосов
/ 31 августа 2011

У меня есть две таблицы книг и тегов, которые связаны многими со многими через таблицу books_tags.Что я хочу сделать, это выбрать все книги, которые имеют один или несколько тегов, таких как "% tag%".Нет проблем.Однако у меня также есть поле group_concat, которое я хочу заполнить всеми тегами, относящимися к выбранной книге.

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

select
  flbdb_books.id,
  flbdb_books.title,
  flbdb_tags.id,
  flbdb_tags.name,
  group_concat(distinct concat('["', flbdb_tags.id, '","', flbdb_tags.name, '"]') separator ',') as tags

from
  flbdb_books

join flbdb_books_tags
  on flbdb_books.id = flbdb_books_tags.book_id
join flbdb_tags 
  on flbdb_tags.id = flbdb_books_tags.tag_id

group by flbdb_books.id;

Thisдает желаемый результат, если у меня нет никаких условий.Я использую PHP и json_decode для чтения поля тегов.Я пробовал три разных способа фильтрации результатов, но ни один из них не работает.

  1. используйте где:

    where flbdb_tags.name like '%poetr%'

    однако этоозначает, что поле тегов (поле, собранное с использованием group_concat) заполняется только этим тегом

  2. , используя

    having flbdb_tags.name like '%poetr%'

    thisне возвращает все книги с тегами поэзия, потому что в некоторых случаях тег поэзии скрывается за другим тегом из-за группы с помощью

  3. с использованием поля group_concat

    having tags like '%poetr%'

    это действительно помогло бы, но мне нужно выполнить поиск без учета регистра, а верхний (теги) не работает

Я надеюсь, что этоясно, что я хочу сделать.

Спасибо

Ответы [ 3 ]

0 голосов
/ 31 августа 2011

Не уверен, что я ясно понимаю, но я бы попытался обернуть ваш исходный выбор и выполнить фильтрацию в обертке выбора

select * from (
select
  flbdb_books.id,
  flbdb_books.title,
  flbdb_tags.id,
  flbdb_tags.name,
  group_concat(distinct concat('["', flbdb_tags.id, '","', flbdb_tags.name, '"]') separator ',') as tags
from
  flbdb_books
join flbdb_books_tags
  on flbdb_books.id = flbdb_books_tags.book_id
join flbdb_tags 
  on flbdb_tags.id = flbdb_books_tags.tag_id
group by flbdb_books.id) inner_select
where upper(inner_select.name) like '%herpderp%'
0 голосов
/ 31 августа 2011

Существует реляционный запрос, который делает именно то, что вам нужно.

Суть в том, что тег фильтра является вашей отправной точкой, и вам действительно нужно присоединиться к тегу и книге обратно к тегам.

select
 books.id,
 books.title,
 tags.id,
 tags.name,

 group_concat(distinct concat('["', tags.id, '","', tags.name, '"]') separator ',') as tags

from flbdb_tags filter_tag

join flbdb_books_tags filter_book_tags 
  on filter_tag.id = filter_book_tags.tag_id

join flbdb_books books
  on filter_book_tags.book_id = books.id

join flbdb_books_tags books_tags
  on books.id = books_tags.book_id

join flbdb_tags tags
  on tags.id = books_tags.tag_id

where filter_tag.name like '%poetr%'

group by books.id;

Вам необходимо присоединиться дважды, а не один раз, поскольку фильтруемый вами тег - это другой набор данных, чем все теги для книги.

0 голосов
/ 31 августа 2011

Будет ли у вас работать?

select
flbdb_books.id,
flbdb_books.title,
COUNT(CASE
WHEN flbdb_tags.name LIKE '%poetr%' THEN 1
END) as num_poetry,  
group_concat(distinct concat('["', flbdb_tags.id, '","', flbdb_tags.name,  
'"]')         separator ',') as tags   
from
flbdb_books

join flbdb_books_tags
on flbdb_books.id = flbdb_books_tags.book_id
join flbdb_tags 
 on flbdb_tags.id = flbdb_books_tags.tag_id

group by flbdb_books.id
HAVING num_poetry >0;
...