查询显示多对多关系中的关联列表
Posted
技术标签:
【中文标题】查询显示多对多关系中的关联列表【英文标题】:Query showing list of associations in many-to-many relationship 【发布时间】:2008-10-06 14:15:04 【问题描述】:我有两个表,Book 和 Tag,并且使用关联表 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
找到有关创建它的说明【讨论】:
以上是关于查询显示多对多关系中的关联列表的主要内容,如果未能解决你的问题,请参考以下文章