web-dev-qa-db-ja.com

サブクエリの複数の結果を単一のコンマ区切り値に結合します

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

TableA
------
ID,
Name

TableB
------
ID,
SomeColumn,
TableA_ID (FK for TableA)

関係は、TableAの1行-TableBの多くです。

今、私はこのような結果を見たいです:

ID     Name      SomeColumn

1.     ABC       X, Y, Z (these are three different rows)
2.     MNO       R, S

これは機能しません(サブクエリの複数の結果):

SELECT ID,
       Name, 
       (SELECT SomeColumn FROM TableB WHERE F_ID=TableA.ID)
FROM TableA

クライアント側で処理を行う場合、これは些細な問題です。しかし、これはすべてのページでXクエリを実行する必要があることを意味します。XはTableAの結果の数です。

TableAの行に対して複数の結果を返すため、単にGROUP BYなどを実行することはできません。

COALESCEなどを利用したUDFが機能するかどうかわかりませんか?

79
Donnie Thomas

1. UDFを作成します。

CREATE FUNCTION CombineValues
(
    @FK_ID INT -- The foreign key from TableA which is used 
               -- to fetch corresponding records
)
RETURNS VARCHAR(8000)
AS
BEGIN
DECLARE @SomeColumnList VARCHAR(8000);

SELECT @SomeColumnList =
    COALESCE(@SomeColumnList + ', ', '') + CAST(SomeColumn AS varchar(20)) 
FROM TableB C
WHERE C.FK_ID = @FK_ID;

RETURN 
(
    SELECT @SomeColumnList
)
END

2.サブクエリで使用:

SELECT ID, Name, dbo.CombineValues(FK_ID) FROM TableA

3.ストアドプロシージャを使用している場合は、次のようにすることができます。

CREATE PROCEDURE GetCombinedValues
 @FK_ID int
As
BEGIN
DECLARE @SomeColumnList VARCHAR(800)
SELECT @SomeColumnList =
    COALESCE(@SomeColumnList + ', ', '') + CAST(SomeColumn AS varchar(20)) 
FROM TableB
WHERE FK_ID = @FK_ID 

Select *, @SomeColumnList as SelectedIds
    FROM 
        TableA
    WHERE 
        FK_ID = @FK_ID 
END
45
Donnie Thomas

これでも目的を果たす

サンプルデータ

declare @t table(id int, name varchar(20),somecolumn varchar(MAX))
insert into @t
    select 1,'ABC','X' union all
    select 1,'ABC','Y' union all
    select 1,'ABC','Z' union all
    select 2,'MNO','R' union all
    select 2,'MNO','S'

クエリ:

SELECT ID,Name,
    STUFF((SELECT ',' + CAST(T2.SomeColumn AS VARCHAR(MAX))
     FROM @T T2 WHERE T1.id = T2.id AND T1.name = T2.name
     FOR XML PATH('')),1,1,'') SOMECOLUMN
FROM @T T1
GROUP BY id,Name

出力:

ID  Name    SomeColumn
1   ABC     X,Y,Z
2   MNO     R,S
129
priyanka.sarkar

あなたはCOALESCEで正しい軌道に乗っていると思います。コンマ区切りの文字列を作成する例については、こちらをご覧ください。

http://www.sqlteam.com/article/using-coalesce-to-build-comma-delimited-string

11
Ben Hoffstein

MySQLには、あなたが求めているものを返す group_concat 関数があります。

SELECT TableA.ID, TableA.Name, group_concat(TableB.SomeColumn) 
as SomColumnGroup FROM TableA LEFT JOIN TableB ON 
TableB.TableA_ID = TableA.ID
10
Jacob

テーブルAにWHERE句しかない場合、次のようにストアドプロシージャを作成します。

SELECT Id, Name From tableA WHERE ...

SELECT tableA.Id AS ParentId, Somecolumn 
FROM tableA INNER JOIN tableB on TableA.Id = TableB.F_Id 
WHERE ...

次に、DataSet dsにそれを入力します。それから

ds.Relations.Add("foo", ds.Tables[0].Columns("Id"), ds.Tables[1].Columns("ParentId"));

最後に、ページにリピーターを追加して、すべての行にコンマを入れることができます

 <asp:DataList ID="Subcategories" DataKeyField="ParentCatId" 
DataSource='<%# Container.DataItem.CreateChildView("foo") %>' RepeatColumns="1"
 RepeatDirection="Horizontal" ItemStyle-HorizontalAlign="left" ItemStyle-VerticalAlign="top" 
runat="server" >

このようにして、クライアント側でそれを行いますが、データベースとフロントエンド間で最小限のデータを渡すクエリを1つだけ使用します

0
Sklivvz

Priyanka.sarkarが言及した解決策を試してみましたが、OPが尋ねたように、それがうまく機能しませんでした。ここに私が終わった解決策があります:

SELECT ID, 
        SUBSTRING((
            SELECT ',' + T2.SomeColumn
            FROM  @T T2 
            WHERE WHERE T1.id = T2.id
            FOR XML PATH('')), 2, 1000000)
    FROM @T T1
GROUP BY ID
0
mrogunlana

より正確な応答を得るには、詳細を提供する必要がある場合があります。

データセットが狭いように見えるため、結果ごとに行を使用し、クライアントで後処理を実行することを検討することができます。

したがって、サーバーに作業を行わせて、次のような結果セットを返すようにしたい場合

ID       Name       SomeColumn
1        ABC        X
1        ABC        Y
1        ABC        Z
2        MNO        R
2        MNO        S

もちろん、これはIDの簡単な内部結合です

クライアントで結果セットを取得したら、CurrentNameという変数を維持し、SomeColumnの収集を目的の有用なものに停止するタイミングをトリガーとして使用します。

0
Bill