SQL - 如何通过链接查询多个表./ associative table

时间:2018-02-19 20:29:08

标签: mysql multiple-tables linked-tables

我在查询多个SQL表并正确连接结果时遇到问题。我有3个表1)一个带有文章的主表,2)一个带有主题标签列表的表,以及一个将标签链接到文章的关联表。
我试着构造以下查询: - 查询主表 - 对于每个结果,在第3个表中获取关联的标签(通过关联表链接) - 没有关联的标签仍然包括主表的结果(我尝试了各种连接)

我花了几天的时间尝试并且可能在stackexchange上阅读了超过30篇帖子,但仍然存在这样的问题:我无法返回所有结果并使标签与主表中的记录正确关联。我尝试过左/外/内关节,但它们都将返回所有记录的所有标记,而不是正确关联它们。

以下是结果正确但所有可用标记都添加到每条记录的第一个示例。 [结果正确但标签错误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';

我非常感谢有关如何将所有结果和标签与主表中的记录正确关联的帮助。

更新:在尝试两个左连接的建议后,我有下面修改过的查询。虽然我现在从主表中获得了所有正确的结果,但所有标签都与每个结果相关联,这不是我想要的(输出显示在附加的第一个图像中)。关于表结构,它对应于一个Nosyara构成,即我有一个中间/关联表,它只包含main和tags表之间的id对(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';

注意:这已经解决了。在Answers下面进一步查看正确的代码。

2 个答案:

答案 0 :(得分: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

答案 1 :(得分:0)

解决方案是1)添加两个左连接,2)将SubjectTags表的声明移动到第二个LEFT JOIN,3)将linkArticlesToSubjectTags表的声明移动到第一个LEFT JOIN,并且4)移动表ids从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';