Domanda

Ho 3 tabelle chiamate:

  • Applicazioni (ID, nome)
  • Risorse (ID, nome)
  • ApplicationsResources (id, app_id, resource_id)

Voglio mostrare su una GUI una tabella con tutti i nomi delle risorse. In una cella di ogni riga vorrei elencare tutte le applicazioni (separate da virgola) di quella risorsa.

Quindi la domanda è: qual è il modo migliore per farlo in SQL in quanto ho bisogno di ottenere tutte le risorse e ho anche bisogno di ottenere tutte le applicazioni per ogni risorsa?

Eseguo prima una selezione * dalle risorse, quindi eseguo il ciclo attraverso ciascuna risorsa ed eseguo una query separata per risorsa per ottenere l'elenco delle applicazioni per quella risorsa?

Esiste un modo per farlo in una query?

È stato utile?

Soluzione

Non c'è modo di farlo in modo indipendente dal DB. Quindi è necessario ottenere l'intero set di dati in questo modo:

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 quindi concatena NomeApp a livello di programmazione mentre raggruppate per ResName .

Altri suggerimenti

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

Raccomando leggere informazioni sull'aggregazione / concatenazione di stringhe in Oracle .

Utilizzo di COALESCE per creare una stringa delimitata da virgole in SQL Server
http://www.sqlteam.com/article/using -coalesce-to-build-delimitato da virgole-string

Esempio:

DECLARE @EmployeeList varchar(100)

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

SELECT @EmployeeList

Non so se esiste una soluzione per farlo in modo indipendente dal database, dal momento che molto probabilmente avrai bisogno di una qualche forma di manipolazione delle stringhe, e queste sono generalmente diverse tra i fornitori.

Per SQL Server 2005 e versioni successive, è possibile utilizzare:

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

Utilizza il costrutto FOR XML PATH di SQL Server 2005 per elencare i componenti secondari (le applicazioni per una determinata risorsa) come un elenco separato da virgole.

Marc

Credo che ciò che vuoi sia:

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

Se stai usando MySQL

Riferimento

Supponendo SQL Server:

Struttura della tabella:

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

Domanda:

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

Risultati:

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

Penso che potremmo scrivere nel seguente modo per recuperare (sotto il codice è solo un esempio, si prega di modificare secondo necessità):

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

Da prossima versione di SQL Server sarai in grado di fare

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 

Per le versioni precedenti del prodotto esiste una grande varietà di approcci diversi a questo problema. Un'ottima recensione è nell'articolo: Concatenazione dei valori di riga in Transact-SQL .

  • Concatenamento di valori quando il numero di elementi non è noto

    • Metodo CTE ricorsivo
    • I metodi XML della blackbox
    • Uso di Common Language Runtime
    • UDF scalare con ricorsione
    • UDF valutato in tabella con un ciclo WHILE
    • SQL dinamico
    • L'approccio del cursore
      .
  • Approcci non affidabili

    • UDF scalare con estensione di aggiornamento t-SQL
    • UDF scalare con concatenazione variabile in 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;

Per essere agnostici, torna indietro 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;

Ora usa il tuo linguaggio di programmazione del server per concatenare a_names mentre r_name è lo stesso dell'ultima volta.

Questo lo farà in SQL Server:

DECLARE @listStr VARCHAR(MAX)
SELECT @listStr = COALESCE(@listStr+',' ,'') + Convert(nvarchar(8),DepartmentId)
FROM Table
SELECT @listStr
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top