SQLクエリを使用してコンマ区切りリストを作成するにはどうすればよいですか?
-
10-07-2019 - |
質問
次の3つのテーブルがあります:
- アプリケーション(id、name)
- リソース(id、name)
- ApplicationsResources(id、app_id、resource_id)
GUIですべてのリソース名のテーブルを表示したい。各行の1つのセルに、そのリソースのすべてのアプリケーション(コンマ区切り)をリストします。
質問は、すべてのリソースを取得する必要があり、各リソースのすべてのアプリケーションを取得する必要があるため、SQLでこれを行う最良の方法は何ですか?
最初にリソースからselect *を実行し、次に各リソースをループし、リソースごとに個別のクエリを実行して、そのリソースのアプリケーションのリストを取得しますか?
1つのクエリでこれを実行する方法はありますか?
解決
DBに依存しない方法でそれを行う方法はありません。 したがって、次のようなデータセット全体を取得する必要があります。
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
そして、 AppName をプログラムで連結し、 ResName でグループ化します。
他のヒント
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
Oracleでの文字列の集約/連結について読む。 / p>
COALESCEを使用してSQL Serverでコンマ区切りの文字列を作成する
http://www.sqlteam.com/article/using -coalesce-to-build-comma-delimited-string
例:
DECLARE @EmployeeList varchar(100)
SELECT @EmployeeList = COALESCE(@EmployeeList + ', ', '') +
CAST(Emp_UniqueID AS varchar(5))
FROM SalesCallsEmployees
WHERE SalCal_UniqueID = 1
SELECT @EmployeeList
データベースに依存しない方法でこれを行うための解決策があるかどうかはわかりません。おそらく何らかの形式の文字列操作が必要になるからです。これらは通常ベンダーによって異なります。
SQL Server 2005以降では、次を使用できます。
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
SQL Server 2005 FOR XML PATH
コンストラクトを使用して、サブアイテム(特定のリソースのアプリケーション)をコンマ区切りリストとしてリストします。
マーク
あなたが望むものは次のとおりです:
SELECT ItemName、GROUP_CONCAT(DepartmentId)FROM table_name GROUP BY ItemName
MySQLを使用している場合
リファレンス
SQL Serverの想定:
テーブル構造:
CREATE TABLE [dbo].[item_dept](
[ItemName] char(20) NULL,
[DepartmentID] int NULL
)
クエリ:
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
結果:
ItemName DepartmentID
item1 21,13,9,36
item2 4,9,44
取得するために次の方法で書くことができると思います(コードは単なる例であり、必要に応じて変更してください):
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
SQL Serverの次のバージョンから、次のことができます。やる
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
以前のバージョンの製品には、この問題に対する非常に幅広いさまざまなアプローチがあります。それらの優れたレビューは記事にあります: Transact-SQLでの行値の連結。
-
アイテムの数が不明な場合の値の連結
- 再帰的CTEメソッド
- ブラックボックスXMLメソッド
- 共通言語ランタイムの使用
- 再帰を使用したスカラーUDF
- WHILEループを持つテーブル値UDF
- 動的SQL
- カーソルアプローチ
。
-
信頼性の低いアプローチ
- t-SQL更新拡張機能を備えたスカラーUDF
- SELECTでの変数連結を含むスカラーUDF
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;
不可知論者になるには、ドロップバックしてパントします。
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;
サーバープログラミング言語を使用して、a_namesを連結します。r_nameは前回と同じです。
これはSQL Serverで実行されます:
DECLARE @listStr VARCHAR(MAX)
SELECT @listStr = COALESCE(@listStr+',' ,'') + Convert(nvarchar(8),DepartmentId)
FROM Table
SELECT @listStr