Wie erstelle ich eine durch Kommata getrennte Liste einer SQL-Abfrage verwenden?
-
10-07-2019 - |
Frage
Ich habe 3 Tabellen genannt:
- Anwendungen (id, name)
- Ressourcen (id, name)
- ApplicationsResources (id, app_id, RESOURCE_ID)
Ich möchte auf einem GUI eine Tabelle aller Ressourcennamen zeigen. In einer Zelle in jeder Zeile würde Ich mag alle Anwendungen zur Liste aus (durch Komma getrennt) diese Ressource.
Die Frage ist also, was ist der beste Weg, dies in SQL zu tun, wie ich alle Ressourcen erhalten müssen, und ich muss auch für jede Ressource alle Anwendungen bekommen?
Habe ich eine wählen laufe * von Ressourcen und dann Schleife durch jede Ressource und hat eine separate Abfrage pro Ressource die Liste der Anwendungen für diese Ressource zu bekommen?
Gibt es eine Weise, die ich dies in einer Abfrage tun?
Lösung
Es gibt keinen Weg, um es in ein DB-agnostische Weise zu tun. Sie müssen also die gesamten Daten-Set wie diese:
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
Und dann Concat die AppName programmatisch , während die Gruppierung von ResName .
Andere Tipps
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
Ich empfehle über String-Aggregation / concatentation in Oracle zu lesen.
COALESCE Mit Komma-separierte String in SQL Server Build
http://www.sqlteam.com/article/using -coalesce-to-build-kommagetrennte-string
Beispiel:
DECLARE @EmployeeList varchar(100)
SELECT @EmployeeList = COALESCE(@EmployeeList + ', ', '') +
CAST(Emp_UniqueID AS varchar(5))
FROM SalesCallsEmployees
WHERE SalCal_UniqueID = 1
SELECT @EmployeeList
Ich weiß nicht, ob es eine Lösung ist das in einer Datenbank-agnostische Weise zu tun, da Sie wahrscheinlich irgendeine Form von String-Manipulation benötigen, und diejenigen sind in der Regel unterschiedlich zwischen den Anbietern.
Für SQL Server 2005 und höher, könnten Sie verwenden:
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
Es verwendet den SQL Server 2005 FOR XML PATH
Konstrukt, um die Unterpunkte Liste (die Anwendungen für eine bestimmte Ressource) als durch Kommata getrennte Liste.
Marc
Ich glaube, was Sie wollen, ist:
SELECT ItemName, GROUP_CONCAT(DepartmentId) FROM table_name GROUP BY ItemName
Wenn Sie mit MySQL
Referenz
Unter der Annahme, SQL Server:
Tabellenstruktur:
CREATE TABLE [dbo].[item_dept](
[ItemName] char(20) NULL,
[DepartmentID] int NULL
)
Abfrage:
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
Ergebnisse:
ItemName DepartmentID
item1 21,13,9,36
item2 4,9,44
ich denke, wir in der folgenden Art und Weise schreiben kann abgerufen werden (Code unten ist nur ein Beispiel, bitte ändern je nach Bedarf):
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
nächste Version von SQL Server Sie in der Lage sein werden, tun
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
Bei früheren Versionen des Produkts gibt es eine ganz große Vielfalt unterschiedlicher Ansätze für dieses Problem. Eine ausgezeichnete Bewertung von ihnen ist in dem Artikel: verketten Row Werte in Transact-SQL .
-
verketten Werte, wenn die Anzahl der Elemente nicht bekannt ist,
- rekursive CTE Methode
- Die Blackbox XML Methoden
- Verwenden von Common Language Runtime
- Scalar UDF mit Rekursion
- Tabelle bewertet UDF mit einer while-Schleife
- Dynamische SQL
- Der Cursor Ansatz
.
-
Nicht zuverlässige Ansätze
- Scalar UDF mit T-SQL-Update-Erweiterung
- Scalar UDF mit variabler Verkettung 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;
Um Agnostiker, fallen zurück und 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;
Jetzt Benutzer Ihr Server Programmiersprache a_names verketten, während r_name das gleiche wie das letzte Mal ist.
Dies wird es in SQL Server tun:
DECLARE @listStr VARCHAR(MAX)
SELECT @listStr = COALESCE(@listStr+',' ,'') + Convert(nvarchar(8),DepartmentId)
FROM Table
SELECT @listStr