从联结表中获取数据作为唯一记录的值列表

时间:2018-06-08 21:55:46

标签: sql sql-server-express junction-table

我有两个表通过联结表连接多对多关系:

    CREATE TABLE [dbo].[User](
    [ID] [int] IDENTITY(1,1) NOT NULL,
    [name] [nvarchar](50) NOT NULL,
    [surname] [nvarchar](50) NOT NULL,
)

    CREATE TABLE [dbo].[Room](
    [ID] [int] IDENTITY(1,1) NOT NULL,
    [number] [nvarchar](50) NOT NULL
)

CREATE TABLE [dbo].[Permission](
    [ID] [int] IDENTITY(1,1) NOT NULL,
    [user_id] [int] NOT NULL,
    [room_id] [int] NOT NULL
)

我想构建一个查询,它会从User表和给定用户有权限的房间列表中提供结果名称和surename。例如:

name surname rooms
Jon  Doe     [134,143,132]

我设法为一个房间的Jon Doe获得了一些结果,但是我无法将其折叠以便为每个用户记录。

1 个答案:

答案 0 :(得分:1)

在2017年之前的SQL Server中,可以使用相关子查询FOR XML来完成。

SELECT [User].[name],
       [User].[surname],
       stuff((SELECT ',' + [Room].[number] [text()]
                     FROM [dbo].[Room]
                          INNER JOIN [dbo].[Permission]
                                     ON [Permission].[room_id] = [Room].[ID]
                          WHERE [Permission].[user_id] = [User].[ID]
              FOR XML PATH('')), 1, 1, NULL) [rooms]
       FROM [dbo].[User];

2017年以来,有一个string_agg()聚合函数,可以将一个组的字符串连接起来。

SELECT [User].[name],
       [User].[surname],
       string_agg([Room].[number], ',') [rooms]
       FROM [dbo].[User]
            INNER JOIN [dbo].[Permission]
                       ON [Permission].[user_id] = [User].[ID]
            INNER JOIN [dbo].[Room]
                       ON [Room].[ID] = [Permission].[room_id]
       GROUP BY [User].[ID],
                [User].[name],
                [User].[surname];

(注意:我确实将[User].[ID]添加到GROUP BY,因为可能有多个同名用户。)