Question

J'ai 3 tables appelées:

  • Applications (identifiant, nom)
  • Ressources (identifiant, nom)
  • ApplicationsResources (id, id_app, id_ressource)

Je souhaite afficher sur une interface graphique un tableau contenant 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?

Existe-t-il un moyen de faire cela en une seule requête?

Était-ce utile?

La solution

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 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

Ensuite, concatrez le nom_app par programmation lors du regroupement par nom_Résque .

Autres conseils

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

Je recommande à d'informations sur le regroupement / la 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-à-construire-chaîne-délimitée

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 forme de manipulation de chaîne, et celles-ci sont généralement différentes entre les vendeurs.

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 la construction FOR XML PATH de SQL Server 2005 pour répertorier les sous-éléments (les applications d'une ressource donnée) sous forme de liste séparée par des virgules.

Marc

Je crois que ce que vous voulez, c'est:

SELECT ItemName, GROUP_CONCAT (DepartmentId) FROM nom_table 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   
)

Requête:

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 est un exemple, veuillez le modifier 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

À partir de la version suivante 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 des valeurs de ligne dans Transact-SQL .

  • Concaténer des valeurs lorsque le nombre d'éléments n'est pas connu

    • Méthode CTE récursive
    • Les méthodes XML de la boîte noire
    • Utilisation du Common Language Runtime
    • UDF scalaire avec récursivité
    • Table UDF avec une boucle WHILE
    • SQL dynamique
    • L'approche du curseur
      .
  • Approches non fiables

    • UDF scalaire avec extension de mise à jour t-SQL
    • Fichier UDF scalaire avec concaténation de variable dans 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;

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;

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 un nom, alors que nom_r est le même que la dernière fois.

Cela se fera dans SQL Server:

DECLARE @listStr VARCHAR(MAX)
SELECT @listStr = COALESCE(@listStr+',' ,'') + Convert(nvarchar(8),DepartmentId)
FROM Table
SELECT @listStr
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top