SQL - Как запросить несколько таблиц через ссылку ./ ассоциативная таблица

0

У меня возникла проблема с запросом нескольких таблиц 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';

ПРИМЕЧАНИЕ. Это было решено. См. Правильный код ниже в разделе "Ответы".

  • 0
    Исходя из вашего описания, это звучит как внешнее соединение со мной. Возможно, если вы добавите схемы таблиц, это облегчит формирование запроса. Примерный набор данных также поможет. Кроме того, если вы добавляете условия в WHERE , это применяется ко всему набору данных. Вместо этого вы хотите условия в предложении ON объединения.
Теги:
multiple-tables
linked-tables

2 ответа

0
Лучший ответ

Вам нужно 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

http://sqlfiddle.com/#!9/a14ef4/1

  • 0
    Спасибо за быстрый ответ. Ваша схема для 3 таблиц соответствует моей, но когда я пробую два левых объединения, в то время как я получаю все правильные результаты из основной таблицы, все теги связаны со всеми результатами, что не является желаемым результатом. Я добавлю свои изменения в исходный вопрос.
  • 0
    В моем примере я использовал название в качестве идентификатора.
Показать ещё 1 комментарий
0

Решение состояло в том, чтобы: 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';

Ещё вопросы

Сообщество Overcoder
Наверх
Меню