Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/sql-server/21.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Sql 显示多对多关系中关联列表的查询_Sql_Sql Server_Database - Fatal编程技术网

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

Sql 显示多对多关系中关联列表的查询,sql,sql-server,database,Sql,Sql Server,Database,我有两个表,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 |

我有两个表,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
有没有一种方法可以在线执行此操作,而不必求助于函数或存储过程?我正在使用SQLServer2005


请注意,中已经提出了相同的问题,但解决方案涉及创建函数。我在问是否有一种方法可以解决这个问题,而不必创建函数或存储过程。

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

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

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

如果你知道一本书的最大标记数,你可以使用枢轴将它们放到同一行,然后使用凝聚,但一般来说,我相信没有。

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

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”),我可以搜索逗号空格字符并用空字符串替换它。这样我就可以去掉最后一个逗号。这假设您的标记中永远不会有这样的字符序列。

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

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”),我可以搜索逗号空格字符并用空字符串替换它。这样我就可以去掉最后一个逗号。这假设您的标记中永远不会有这样的字符序列。

最干净的解决方案可能是使用自定义的C#CLR聚合函数。我们发现这种方法非常有效。您可以在

找到创建此函数的说明最干净的解决方案可能是使用自定义的C#CLR聚合函数。我们发现这种方法非常有效。您可以在

上找到创建此文件的说明,我不知道标签ID是什么-这就是报告的目的:)我不知道标签ID是什么-这就是报告的目的:)