web-dev-qa-db-ja.com

SQLクエリを使用してコンマ区切りリストを作成するにはどうすればよいですか?

次の3つのテーブルがあります。

  • アプリケーション(id、name)
  • リソース(id、name)
  • ApplicationsResources(id、app_id、resource_id)

すべてのリソース名のテーブルをGUIに表示したい。各行の1つのセルに、そのリソースのすべてのアプリケーション(コンマ区切り)をリストします。

すべてのリソースを取得する必要があり、各リソースのすべてのアプリケーションを取得する必要があるため、SQLでこれを行う最良の方法は何ですか?

最初にリソースからselect *を実行してから、各リソースをループし、リソースごとに個別のクエリを実行して、そのリソースのアプリケーションのリストを取得しますか?

1つのクエリでこれを行う方法はありますか?

53
leora

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

そして、AppNameprogrammaticallyを連結し、ResNameでグループ化します。

0

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の文字列の集約/連結について読む をお勧めします。

115
OMG Ponies

SQL ServerでCOALESCEを使用してコンマ区切り文字列を作成する
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
26
Robert Harvey

データベースに依存しない方法でこれを行うための解決策があるかどうかはわかりません。なぜなら、おそらく何らかの形式の文字列操作が必要になるからです。それらは通常ベンダーによって異なります。

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コンストラクトを使用して、サブアイテム(特定のリソースのアプリケーション)をコンマ区切りリストとしてリストします。

マーク

11
marc_s

あなたが望むのは

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

MySQLを使用している場合

参照

5
Jamie Wong

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

取得するために次の方法で書くことができると思います(コードは単なる例であり、必要に応じて変更してください):

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

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
4
Martin Smith

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;
2
Pavel Zimogorov

これはSQL Serverでそれを行います:

DECLARE @listStr VARCHAR(MAX)
SELECT @listStr = COALESCE(@listStr+',' ,'') + Convert(nvarchar(8),DepartmentId)
FROM Table
SELECT @listStr
1
Abe Miessler

不可知論者であるために、ドロップバックしてパントします。

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_nameを連結します。r_nameは前回と同じです。

1
Don