У меня возникла проблема с запросом нескольких таблиц SQL и правильной обработкой результатов. У меня 3 таблицы 1) главная таблица со статьями, 2) таблица со списком тематических тегов и 3) ассоциативная таблица, связывающая теги с статьями.
Я попытался построить следующий запрос: - Запросить основную таблицу - для каждого результата получить связанные теги в третьей таблице (связанные ассоциативной таблицей) - там, где нет привязанных тегов, все равно включают результаты из основной таблицы (я попробовал различные объединения)
Я потратил пару дней, пытаясь, возможно, читать более 30 сообщений в stackexchange, но все еще имею проблему, что я не могу как вернуть все результаты, так и правильно привязать теги к записям в основной таблице. Я пробовал левые/внешние/внутренние суставы, но все они вернут все теги для всех записей, а не свяжут их правильно.
Вот первый пример, когда результаты верны, но все доступные теги добавляются к каждой записи. [Результаты правильные, но теги неправильные 1
Вот второй пример, где теги правильно связаны с результатами, но результаты без тегов не возвращаются [Тэги правильные, но результаты без тегов не включены 2
Вот один код SQL (соответствующий второму снимку экрана).
SELECT
Ar.Title,
Ar.Analysis_CategoryLevelOne_Name AS MainCategory,
Ar.Analysis_CategoryLevelTwo_Name AS SubCategory,
null AS GenericName,
Ar.Summary,
Ar.Author AS Source,
'Article' AS ContentType,
MATCH (Ar.Title, Summary, Content)
AGAINST ('a*' IN BOOLEAN MODE) AS Relevance,
GROUP_CONCAT(Su.Name) AS Tags
FROM 'conArticles' AS Ar,
'refSubjectTags' AS Su,
'linkArticlesToSubjectTags' AS Link
WHERE MATCH (Title, Summary, Content)
AGAINST ('a*' IN BOOLEAN MODE) AND CurrentOrBackup = 'Current'
AND Ar.Articles_id = Link.linkArticlesToSubjectTags_Articles_Id
AND Link.linkArticlesToSubjectTags_SubjectTags_Id = Su.SubjectTags_Id
GROUP BY Ar.Articles_Id
ORDER BY 'Relevance' 'DESC';
Я был бы очень признателен за помощь в том, как и получить все результаты и теги, которые правильно связаны с записями в главной таблице.
UPDATE: после того, как вы попросили два левых соединения, я получил ниже пересмотренный запрос. Пока я получаю все правильные результаты из основной таблицы, все теги связаны с каждым результатом, чего я не хочу (результат показан на первом прикрепленном изображении). Что касается структуры таблицы, она соответствует той, что была указана в Nosyara, т.е. У меня есть промежуточная/ассоциативная таблица, которая содержит только пары идентификаторов между основной и табличной таблицами (Articles_Id <=> SubjectTags_Id). Я добавил скриншот из ассоциативной таблицы [Ассоциативная таблица 3
SELECT
Ar.Title,
Ar.Analysis_CategoryLevelOne_Name AS MainCategory,
Ar.Analysis_CategoryLevelTwo_Name AS SubCategory,
null AS GenericName,
Ar.Summary,
Ar.Author AS Source,
'Article' AS ContentType,
MATCH (Ar.Title, Summary, Content)
AGAINST ('a*' IN BOOLEAN MODE) AS Relevance,
GROUP_CONCAT(Su.Name) AS Tags
FROM 'refSubjectTags' AS Su,
'conArticles' AS Ar
LEFT JOIN linkArticlesToSubjectTags Link
ON Ar.Articles_id = Link.linkArticlesToSubjectTags_Articles_Id
LEFT JOIN refSubjectTags Su2
ON Link.linkArticlesToSubjectTags_SubjectTags_Id = Su2.SubjectTags_Id
WHERE MATCH (Title, Summary, Content)
AGAINST ('a*' IN BOOLEAN MODE)
GROUP BY Ar.Articles_Id
ORDER BY 'Relevance' 'DESC';
ПРИМЕЧАНИЕ. Это было решено. См. Правильный код ниже в разделе "Ответы".
Вам нужно 2 левых соединения.
Здесь я создал упрощенную схему
CREATE TABLE IF NOT EXISTS 'main' ( 'title' varchar(200));
CREATE TABLE IF NOT EXISTS 'tags' ( id int(10), 'Name' varchar(200));
CREATE TABLE IF NOT EXISTS 'links' ( 'title' varchar(200), 'tag' int(10));
INSERT INTO main VALUES ('Foo'), ('Bar'), ('Baz');
INSERT INTO tags VALUES (1, 'tag1'), (2, 'tag2'), (3, 'tag3'), (4, 'tag4');
INSERT INTO links VALUES ('Foo', 1), ('Foo', 2), ('Bar', 3), ('Bar', 4), ('Hello', 5), ('Foo', 6);
И это SQL:
select ar.title, group_concat(t.name) as tags
from main ar
left join links lnk on ar.title=lnk.title
left join tags t on lnk.tag = t.id
group by title
Выход:
title tags
----- -----
Bar tag3,tag4
Baz (null)
Foo tag1,tag2
Решение состояло в том, чтобы: 1) добавить два левых соединения, 2) переместить объявление таблицы SubjectTags во второй LEFT JOIN, 3) перенести объявление таблицы linkArticlesToSubjectTags в 1-й LEFT JOIN и 4) переместить ассоциации идентификаторов таблиц от WHERE CLAUSE до LEFT JOINS.
Ниже приведен правильный код:
SELECT
Ar.Title,
Ar.Analysis_CategoryLevelOne_Name AS MainCategory,
Ar.Analysis_CategoryLevelTwo_Name AS SubCategory,
null AS GenericName,
Ar.Summary,
Ar.Author AS Source,
'Article' AS ContentType,
MATCH (Ar.Title, Summary, Content)
AGAINST ('employ*' IN BOOLEAN MODE) AS Relevance,
GROUP_CONCAT(Su.Name) AS Tags
FROM 'conArticles' AS Ar
LEFT JOIN linkArticlesToSubjectTags Link
ON Ar.Articles_id = Link.linkArticlesToSubjectTags_Articles_Id
LEFT JOIN refSubjectTags Su
ON Link.linkArticlesToSubjectTags_SubjectTags_Id = Su.SubjectTags_Id
WHERE MATCH (Title, Summary, Content)
AGAINST ('employ*' IN BOOLEAN MODE)
GROUP BY Ar.Articles_Id
ORDER BY 'Relevance' 'DESC';
Ниже приведен оригинальный неправильный код:
SELECT
Ar.Title,
Ar.Analysis_CategoryLevelOne_Name AS MainCategory,
Ar.Analysis_CategoryLevelTwo_Name AS SubCategory,
null AS GenericName,
Ar.Summary,
Ar.Author AS Source,
'Article' AS ContentType,
GROUP_CONCAT(Su.Name) AS Tags
FROM
'refSubjectTags' Su, **[ Move to 2nd LEFT JOIN ]**
'conArticles' Ar,
'linkArticlesToSubjectTags' Link **[ Move to 1st LEFT JOIN ]**
**[ Add the 2 LEFT JOINS ]**
WHERE MATCH (Title, Summary, Content)
AGAINST ('a*' IN BOOLEAN MODE)
AND Ar.Articles_id = Link.linkArticlesToSubjectTags_Articles_Id
AND Link.linkArticlesToSubjectTags_SubjectTags_Id = Su.SubjectTags_Id
**[ The 2 lines above needs to be moved to the 2 LEFT JOINS ]**
GROUP BY Ar.Articles_Id
ORDER BY 'Relevance' 'DESC';
WHERE
, это применяется ко всему набору данных. Вместо этого вы хотите условия в предложенииON
объединения.