如何使用SQL查询创build逗号分隔列表?

我有3个表称为:

  • 应用程序(ID,名称)
  • 资源(id,名称)
  • ApplicationsResources(id,app_id,resource_id)

我想在GUI上显示所有资源名称的表格。 在每一行中的一个单元格中,我想列出所有的资源的应用程序(以逗号分隔)。

所以问题是,在SQL中这样做的最好方法是什么,因为我需要获取所有资源,并且还需要获取每个资源的所有应用程序?

我是否首先从资源运行select *,然后循环遍历每个资源,并对每个资源执行单独的查询以获取该资源的应用程序列表?

有一种方法,我可以在一个查询中做到这一点?

没有办法以数据库不可知的方式做到这一点。 所以你需要像这样得到整个数据集:

select r.name as ResName, a.name as AppName from Resouces as r, Applications as a, ApplicationsResources as ar where ar.app_id = a.id and ar.resource_id = r.id 

然后以ResName编组的同时以编程方式连接AppName

MySQL的

  SELECT r.name, GROUP_CONCAT(a.name SEPARATOR ',') FROM RESOURCES r JOIN APPLICATIONSRESOURCES ar ON ar.resource_id = r.id JOIN APPLICATIONS a ON a.id = ar.app_id GROUP BY r.name 

SQL Server(2005+)

 SELECT r.name, STUFF((SELECT ','+ a.name FROM APPLICATIONS a JOIN APPLICATIONRESOURCES ar ON ar.app_id = a.id WHERE ar.resource_id = r.id GROUP BY a.name FOR XML PATH(''), TYPE).value('.','VARCHAR(max)'), 1, 1, '') FROM RESOURCES r 

SQL Server(2017+)

  SELECT r.name, STRING_AGG(a.name, ',') FROM RESOURCES r JOIN APPLICATIONSRESOURCES ar ON ar.resource_id = r.id JOIN APPLICATIONS a ON a.id = ar.app_id GROUP BY r.name 

神谕

我build议阅读关于Oracle中的string聚合/并列 。

使用COALESCE在SQL Server中构build逗号分隔的string
http://www.sqlteam.com/article/using-coalesce-to-build-comma-delimited-string

例:

 DECLARE @EmployeeList varchar(100) SELECT @EmployeeList = COALESCE(@EmployeeList + ', ', '') + CAST(Emp_UniqueID AS varchar(5)) FROM SalesCallsEmployees WHERE SalCal_UniqueID = 1 SELECT @EmployeeList 

我不知道是否有任何解决scheme以数据库不可知的方式执行此操作,因为您很可能需要某种forms的string操作,而这些操作在供应商之间通常是不同的。

对于SQL Server 2005及更高版本,您可以使用:

 SELECT r.ID, r.Name, Resources = STUFF( (SELECT ','+a.Name FROM dbo.Applications a INNER JOIN dbo.ApplicationsResources ar ON ar.app_id = a.id WHERE ar.resource_id = r.id FOR XML PATH('')), 1, 1, '') FROM dbo.Resources r 

它使用SQL Server 2005 FOR XML PATH构造将子项(给定资源的应用程序)列为逗号分隔列表。

渣子

我相信你想要的是:

SELECT ItemName, GROUP_CONCAT(DepartmentId) FROM table_name GROUP BY ItemName

如果你使用MySQL

参考

假设SQL Server:

表结构:

 CREATE TABLE [dbo].[item_dept]( [ItemName] char(20) NULL, [DepartmentID] int NULL ) 

查询:

 SELECT ItemName, STUFF((SELECT ',' + rtrim(convert(char(10),DepartmentID)) FROM item_dept b WHERE a.ItemName = b.ItemName FOR XML PATH('')),1,1,'') DepartmentID FROM item_dept a GROUP BY ItemName 

结果:

 ItemName DepartmentID item1 21,13,9,36 item2 4,9,44 

我想我们可以用下面的方式来编写检索(下面的代码只是一个例子,请根据需要修改):

 Create FUNCTION dbo.ufnGetEmployeeMultiple(@DepartmentID int) RETURNS VARCHAR(1000) AS BEGIN DECLARE @Employeelist varchar(1000) SELECT @Employeelist = COALESCE(@Employeelist + ', ', '') + E.LoginID FROM humanresources.Employee E Left JOIN humanresources.EmployeeDepartmentHistory H ON E.BusinessEntityID = H.BusinessEntityID INNER JOIN HumanResources.Department D ON H.DepartmentID = D.DepartmentID Where H.DepartmentID = @DepartmentID Return @Employeelist END SELECT D.name as Department, dbo.ufnGetEmployeeMultiple (D.DepartmentID)as Employees FROM HumanResources.Department D SELECT Distinct (D.name) as Department, dbo.ufnGetEmployeeMultiple (D.DepartmentID) as Employees FROM HumanResources.Department D 

从SQL Server的下一个版本,你将能够做到

 SELECT r.name, STRING_AGG(a.name, ',') FROM RESOURCES r JOIN APPLICATIONSRESOURCES ar ON ar.resource_id = r.id JOIN APPLICATIONS a ON a.id = ar.app_id GROUP BY r.name 

对于以前版本的产品,这个问题有很多不同的方法。 在文章中: 对Transact-SQL中的行值进行连接 。

  • 当物品数量未知时,连接值

    • recursionCTE方法
    • 黑盒子的XML方法
    • 使用公共语言运行时
    • 具有recursion的标量UDF
    • 带有WHILE循环的表值UDF
    • dynamicSQL
    • 光标方法
  • 不可靠的方法

    • 具有t-SQL更新扩展的标量UDF
    • 在SELECT中使用variables级联的标量UDF

MySQL的

  SELECT r.name, GROUP_CONCAT(a.name SEPARATOR ',') FROM RESOURCES r JOIN APPLICATIONSRESOURCES ar ON ar.resource_id = r.id JOIN APPLICATIONS a ON a.id = ar.app_id GROUP BY r.name 

**


MS SQL Server

 SELECT r.name, STUFF((SELECT ','+ a.name FROM APPLICATIONS a JOIN APPLICATIONRESOURCES ar ON ar.app_id = a.id WHERE ar.resource_id = r.id GROUP BY a.name FOR XML PATH(''), TYPE).value('.','VARCHAR(max)'), 1, 1, '') FROM RESOURCES r GROUP BY deptno; 

神谕

  SELECT r.name, LISTAGG(a.name SEPARATOR ',') WITHIN GROUP (ORDER BY a.name) FROM RESOURCES r JOIN APPLICATIONSRESOURCES ar ON ar.resource_id = r.id JOIN APPLICATIONS a ON a.id = ar.app_id GROUP BY r.name; 

为了不可知论,放弃和平底船。

 Select a.name as a_name, r.name as r_name from ApplicationsResource ar, Applications a, Resources r where a.id = ar.app_id and r.id = ar.resource_id order by r.name, a.name; 

现在使用你的服务器编程语言连接a_names,而r_name和上次一样。

这将在SQL Server中完成:

 DECLARE @listStr VARCHAR(MAX) SELECT @listStr = COALESCE(@listStr+',' ,'') + Convert(nvarchar(8),DepartmentId) FROM Table SELECT @listStr