Como posso criar uma lista separada por vírgulas usando uma consulta SQL?
-
10-07-2019 - |
Pergunta
Eu tenho 3 tabelas chamado:
- Applications (id, nome)
- Recursos (id, nome)
- ApplicationsResources (id, app_id, RESOURCE_ID)
Eu quero mostrar em uma GUI uma tabela de todos os nomes de recursos. Em uma célula em cada linha Eu gostaria de listar todas as aplicações (separados por vírgula) desse recurso.
Então a questão é, qual é a melhor maneira de fazer isso em SQL como eu preciso para obter todos os recursos e eu também precisa obter todas as aplicações para cada recurso?
Eu executar um select * from recursos primeiro e depois percorrer cada recurso e fazer uma consulta separada por recurso para obter a lista de aplicativos para esse recurso?
Existe uma maneira eu posso fazer isso em uma consulta?
Solução
Não há nenhuma maneira de fazê-lo de uma forma DB-agnóstico. Então você precisa para obter o conjunto de dados definido como este:
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
E então concat o AppName programação , enquanto agrupamento por ResName .
Outras dicas
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
A Oracle
Eu recomendo ler sobre cadeia de agregação / concatentation no Oracle .
Usando COALESCE construir delimitado por vírgula de Cordas em SQL Server
http://www.sqlteam.com/article/using -coalesce-to-build-vírgula-delimitado por corda
Exemplo:
DECLARE @EmployeeList varchar(100)
SELECT @EmployeeList = COALESCE(@EmployeeList + ', ', '') +
CAST(Emp_UniqueID AS varchar(5))
FROM SalesCallsEmployees
WHERE SalCal_UniqueID = 1
SELECT @EmployeeList
Eu não sei se há alguma solução para fazer isso de uma forma de banco de dados agnóstica, já que você provavelmente irá precisar de alguma forma de manipulação de cadeia, e esses são normalmente diferentes entre fornecedores.
Para o SQL Server 2005 e acima, você pode usar:
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
Ele usa o SQL Server 2005 construção FOR XML PATH
para listar os subitens (os pedidos de um determinado recurso) como uma lista separada por vírgulas.
Marc
Eu acredito que o que você quer é:
SELECT ItemName, GROUP_CONCAT(DepartmentId) FROM table_name GROUP BY ItemName
Se você estiver usando MySQL
Referência
Assumindo SQL Server:
Estrutura da tabela:
CREATE TABLE [dbo].[item_dept](
[ItemName] char(20) NULL,
[DepartmentID] int NULL
)
Inquérito:
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
Resultado:
ItemName DepartmentID
item1 21,13,9,36
item2 4,9,44
Eu acho que poderia escrever da seguinte maneira para recuperar (o código abaixo é apenas um exemplo, por favor modifique conforme necessário):
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
A partir próxima versão do SQL Server você será capaz de fazer
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
Para versões anteriores do produto há muito uma grande variedade de abordagens diferentes para este problema. Uma excelente revisão deles é no artigo: Valores Concatenando fileira em Transact-SQL .
-
A concatenação de valores quando o número de itens não são conhecidos
- método recursiva CTE
- Os métodos XML blackbox
- Usando Common Language Runtime
- Scalar UDF com recursão
- Tabela valorizado UDF com um tempo loop
- Dinâmico SQL
- O Cursor abordagem
.
-
abordagens não-confiáveis ??
- Scalar UDF com extensão atualização t-SQL
- Scalar UDF com concatenação variável no SELECT
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;
do Oracle
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;
Para ser agnóstico, back drop e punt.
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;
Agora o usuário sua linguagem de programação do servidor para a_names concatenar enquanto r_name é o mesmo que da última vez.
Isso vai fazê-lo em SQL Server:
DECLARE @listStr VARCHAR(MAX)
SELECT @listStr = COALESCE(@listStr+',' ,'') + Convert(nvarchar(8),DepartmentId)
FROM Table
SELECT @listStr