[sql-server] 하위 쿼리의 여러 결과를 단일 쉼표로 구분 된 값으로 결합

두 개의 테이블이 있습니다.

TableA
------
ID,
Name

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

관계는 하나 개의 행 TableA의 많은 – 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.

의 행에 대해 여러 결과를 반환하므로 단순히 GROUP BY 또는 이와 유사한 작업을 수행 할 수 없습니다 TableA.

COALESCE 또는 이와 유사한 것을 활용하는 UDF가 작동하는지 확실하지 않습니까?



답변

이것조차도 목적을 달성 할 것입니다

샘플 데이터

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


답변

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


답변

나는 당신이 COALESCE와 올바른 길을 가고 있다고 생각합니다. 쉼표로 구분 된 문자열을 작성하는 예는 여기를 참조하십시오.

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


답변

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


답변

보다 정확한 응답을 위해 더 자세한 정보를 제공해야 할 수도 있습니다.

데이터 세트가 좁아 보이므로 결과 당 행을 사용하고 클라이언트에서 후 처리를 수행하는 것을 고려할 수 있습니다.

따라서 서버를 실제로 만들고 싶다면 작업이 다음과 같은 결과 집합을 반환합니다.

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

물론 간단한 INNER JOIN on ID

결과 집합을 클라이언트에 다시 가져 오면 CurrentName이라는 변수를 유지하고 원하는 유용한 작업에 SomeColumn 수집을 중지 할 때 트리거로 사용합니다.


답변

테이블 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" >

이런 식으로 클라이언트 측에서 수행하지만 하나의 쿼리로 데이터베이스와 프런트 엔드간에 최소한의 데이터를 전달합니다.


답변

나는 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