如何使用 SQL 查询创建逗号分隔的列表?
-
10-07-2019 - |
题
我有 3 个表,名为:
- 应用程序(ID、名称)
- 资源(id、名称)
- 应用程序资源(id、app_id、resource_id)
我想在 GUI 上显示所有资源名称的表格。在每一行的一个单元格中,我想列出该资源的所有应用程序(以逗号分隔)。
所以问题是,在 SQL 中执行此操作的最佳方法是什么,因为我需要获取所有资源,并且还需要获取每个资源的所有应用程序?
我是否首先运行 select * from resources,然后循环遍历每个资源并对每个资源执行单独的查询以获取该资源的应用程序列表?
有没有一种方法可以在一个查询中完成此操作?
解决方案
没有办法以与数据库无关的方式来做到这一点。所以你需要像这样获取整个数据集:
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
然后连接 应用程序名称 以编程方式 分组时按 资源名称.
其他提示
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
甲骨文
我建议 阅读 Oracle 中的字符串聚合/串联.
使用 COALESCE 在 SQL Server 中构建逗号分隔字符串
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
我不知道是否有任何解决方案可以以与数据库无关的方式执行此操作,因为您很可能需要某种形式的字符串操作,而供应商之间的操作通常有所不同。
对于 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 中连接行值.
当项目数量未知时连接值
- 递归CTE方法
- 黑盒 XML 方法
- 使用公共语言运行时
- 具有递归的标量 UDF
- 带有 WHILE 循环的表值 UDF
- 动态SQL
- 游标方法
.
不可靠的方法
- 具有 t-SQL 更新扩展的标量 UDF
- SELECT 中具有变量串联的标量 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
**
微软SQL服务器
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