Вывод sql запроса с условием и использованием GROUP_CONCAT
Есть 3 таблицы со связью 1 ко многим.
(Project)-> там находятся все проекты.
CREATE TABLE `project` (
`id` int(11) NOT NULL,
`name` varchar(255) NOT NULL,
`description` varchar(255) NOT NULL DEFAULT 'Нет описания',
`image` text,
`link` varchar(255) NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
(Tags)-> там находятся теги.
CREATE TABLE `tags` (
`id` int(11) NOT NULL,
`tag_name` varchar(255) NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
(P_tags)-> там находятся id проекта и id тега.
CREATE TABLE `p_tags` (
`project_id` int(11) NOT NULL,
`tag_id` int(11) NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
На данный момент у меня получился такой запрос
SELECT project.id, project.name, project.description, project.image, project.link, GROUP_CONCAT(tags.tag_name) as tags
FROM project
LEFT Join p_tags
ON project.id = p_tags.project_id
INNER JOIN tags
ON tags.id = p_tags.tag_id
WHERE tag_name = '".$tag_filter."'
GROUP BY project.id
$tag_filter - это название тега.
На данный момент он мне выводит: все значения которые написаны в запросе, но в поле tags выводится только одно название.
Мне нужно чтобы выводилось несколько названий из таблицы
Например:
Сейчас выводится такая конструкция
id = 1, name = QuickSettingsTile, description = Simple... tags = java
А мне нужно чтобы выводилось так
id = 1, name = QuickSettingsTile, description = Simple... tags = java,kotlin,html
Ответы (2 шт):
Примерно вот так:
SELECT
project.id,
project.name,
project.description,
project.image,
project.link,
GROUP_CONCAT(DISTINCT tags.tag_name ORDER BY tags.tag_name ASC SEPARATOR ', ') AS tags
FROM
project
LEFT JOIN
p_tags ON project.id = p_tags.project_id
LEFT JOIN
tags ON tags.id = p_tags.tag_id
GROUP BY
project.id,
project.name,
project.description,
project.image,
project.link
Ну а фильтрацию тегов на допустимость - можно вставить уже потом.
Просто проверяем, что требуемый тег имеется в списке тегов, связанных с проектом:
SELECT p.*, GROUP_CONCAT(DISTINCT tags.tag_name) as tags
FROM project
JOIN p_tags ON project.id = p_tags.project_id
JOIN tags ON tags.id = p_tags.tag_id
GROUP BY p.id
HAVING SUM(tag_name = 'требуемый тег');
Если тег есть среди всех тегов, сравнение для него вернёт 1, сумма будет больше нуля, и запись проекта будет отобрана.
Если тега нет, все сравнения дадут ноль, сумма будет ноль, запись проекта не будет отобрана.
Поскольку нужно наличие определённого тега, достаточно внутреннего связывания (INNER JOIN, ну или просто JOIN), левое связывание не требуется.
Если project.id не определён как первичный ключ (в тексте вопроса - этого нет), то следует в GROUP BY перечислить ВСЕ поля таблицы project, которые будут присутствовать в списке вывода. А по-хорошему, и вместо звезды в списке вывода следует также перечислить все поля.
Если в p_tags имеется естественный первичный ключ, включающий оба поля, то DISTINCT в параметрах GROUP_CONCAT() - лишний и может быть удалён.