J'ai 3 tables appelées:
Je veux montrer sur une interface graphique une table de tous les noms de ressources. Dans une cellule de chaque ligne, j'aimerais répertorier toutes les applications (séparées par des virgules) de cette ressource.
La question est donc de savoir quel est le meilleur moyen de le faire en SQL, car je dois obtenir toutes les ressources et obtenir toutes les applications pour chaque ressource.
Dois-je d'abord exécuter une sélection de ressources, puis parcourir chaque ressource et effectuer une requête distincte par ressource pour obtenir la liste des applications de cette ressource?
Est-il possible de le faire en une seule requête?
Il n'y a aucun moyen de le faire d'une manière agnostique à la base de données. Vous devez donc obtenir l'ensemble de données complet comme ceci:
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
Et ensuite concattez le AppNamepar programme lors du regroupement par ResName.
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
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
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
Je recommande lecture sur l'agrégation/concaténation de chaînes dans Oracle .
Utilisation de COALESCE pour créer une chaîne délimitée par des virgules dans SQL Server
http://www.sqlteam.com/article/using-coalesce-to-build-comma-delimited-string
Exemple:
DECLARE @EmployeeList varchar(100)
SELECT @EmployeeList = COALESCE(@EmployeeList + ', ', '') +
CAST(Emp_UniqueID AS varchar(5))
FROM SalesCallsEmployees
WHERE SalCal_UniqueID = 1
SELECT @EmployeeList
Je ne sais pas s'il existe une solution pour le faire d'une manière agnostique à la base de données, car vous aurez probablement besoin d'une certaine forme de manipulation de chaîne, et celles-ci sont généralement différentes entre les fournisseurs.
Pour SQL Server 2005 et versions ultérieures, vous pouvez utiliser:
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
Il utilise le SQL Server 2005 FOR XML PATH
construction pour lister les sous-éléments (les applications d’une ressource donnée) en tant que liste séparée par des virgules.
Marc
Je crois que ce que tu veux c'est:
SELECT ItemName, GROUP_CONCAT(DepartmentId) FROM table_name GROUP BY ItemName
Si vous utilisez MySQL
Référence
En supposant que SQL Server:
Structure de la table:
CREATE TABLE [dbo].[item_dept](
[ItemName] char(20) NULL,
[DepartmentID] int NULL
)
Question:
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
Résultats:
ItemName DepartmentID
item1 21,13,9,36
item2 4,9,44
Je pense que nous pourrions écrire de la manière suivante pour récupérer (le code ci-dessous n'est qu'un exemple, modifiez-le au besoin):
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
De prochaine version de SQL Server vous pourrez faire
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
Les versions précédentes du produit offrent une grande variété d'approches différentes à ce problème. Vous trouverez une excellente critique d’eux dans l’article: Concaténation de valeurs de ligne dans Transact-SQL .
Concaténer des valeurs lorsque le nombre d'éléments n'est pas connu
Approches non fiables
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;
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;
Cela le fera dans SQL Server:
DECLARE @listStr VARCHAR(MAX)
SELECT @listStr = COALESCE(@listStr+',' ,'') + Convert(nvarchar(8),DepartmentId)
FROM Table
SELECT @listStr
Pour être agnostique, redescendre et 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;
Maintenant, utilisez votre langage de programmation serveur pour concaténer a_names alors que r_name est identique à la dernière fois.