查询显示多对多关系中的关联列表

Posted

技术标签:

【中文标题】查询显示多对多关系中的关联列表【英文标题】:Query showing list of associations in many-to-many relationship 【发布时间】:2008-10-06 14:15:04 【问题描述】:

我有两个表,BookTag,并且使用关联表 BookTag 标记书籍。我想创建一个包含书籍列表的报告,并为每本书创建一个书籍标签列表。标签 ID 就足够了,标签名称不是必需的。

例子:

Book table:
Book ID | Book Name
28      | Dracula

BookTag table:
Book ID | Tag ID
28      | 101
28      | 102

在我的报告中,我想显示第 28 本书的标签为 101 和 102:

Book ID | Book Name | Tags
28      | Dracula   | 101, 102

有没有一种方法可以在线执行此操作,而无需求助于函数或存储过程?我使用的是 SQL Server 2005。

请注意,Combine multiple results in a subquery into a single comma-separated value 中已经提出了相同的问题,但解决方案涉及创建一个函数。我在问是否有办法解决这个问题,而无需创建函数或存储过程。

【问题讨论】:

【参考方案1】:

你几乎可以做到。我没有解决的唯一问题是逗号分隔符。这是一个关于使用空格分隔标签的类似结构的查询。

SELECT em.Code,
    (SELECT et.Name + ' '  AS 'data()'
        FROM tblEmployeeTag et
            JOIN tblEmployeeTagAssignment eta ON et.Id = eta.EmployeeTag_Id AND eta.Employee_Id = em.id
    FOR XML PATH('') ) AS Tags
FROM tblEmployee em

编辑:

这是使用您的表格并使用逗号分隔符的完整版本:

SELECT bk.Id AS BookId,
        bk.Name AS BookName,
    REPLACE((SELECT LTRIM(STR(bt.TagId)) + ', '  AS 'data()'
        FROM BookTag bt
        WHERE bt.BookId = bk.Id         
        FOR XML PATH('') ) + 'x', ', x','') AS Tags
FROM Book bk

我想为了将来的参考,我应该解释一下发生了什么。 'data()' 列名是与 FOR XML PATH 语句相关的特殊值。它会导致 XML 文档被呈现,就像您在生成的 XML 的根节点上执行了 .InnerText 一样。 REPLACE 语句是删除尾随逗号的技巧。通过将唯一字符(我随机选择'x')附加到标签列表的末尾,我可以搜索逗号空格字符并将其替换为空字符串。这让我可以只去掉最后一个逗号。这假定您永远不会在标签中包含该字符序列。

【讨论】:

【参考方案2】:

除非您知道标签 ID/名称是什么并且可以将它们硬编码到您的查询中,否则恐怕答案是否定的。

【讨论】:

恐怕我不知道标签 ID 是什么 - 这就是报告的用途 :)【参考方案3】:

如果您知道一本书的最大标签数,您可以使用枢轴将它们放到同一行,然后使用 COALESCE,但总的来说,我不相信有。

【讨论】:

【参考方案4】:

最简洁的解决方案可能是使用自定义 C# CLR 聚合函数。我们发现这非常有效。您可以在 http://dotnet-enthusiast.blogspot.com/2007/05/user-defined-aggregate-function-in-sql.html

找到有关创建它的说明

【讨论】:

以上是关于查询显示多对多关系中的关联列表的主要内容,如果未能解决你的问题,请参考以下文章

NHibernate教程(11)--多对多关联查询

TP中的模型关联的多对多关系

多对多关系的查询集按列表中的匹配数排序

mybatis11--多对多关联查询

使用 Prisma 通过关联表查询多对多关系

hibernate关联关系(多对多)