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

时间:2008-10-06 14:15:05

标签: sql sql-server database

我有两个表,预订标记,并使用关联表 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已经提出了同样的问题,但解决方案涉及创建一个函数。我问是否有办法解决这个问题,而无需创建函数或存储过程。

4 个答案:

答案 0 :(得分:4)

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

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'),我可以搜索逗号空格字符并用空字符串替换它。这让我可以删掉最后一个逗号。这假设您永远不会在标签中包含该字符序列。

答案 1 :(得分:0)

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

答案 2 :(得分:0)

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

答案 3 :(得分:0)

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

找到有关创建此信息的说明