Połącz wiele wyników w zapytaniu podrzędnym w jedną wartość oddzieloną przecinkami

Mam dwa stoły:

TableA
------
ID,
Name

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

Relacja jest jednym rzędem TableA - Wielu TableB.

Teraz chcę zobaczyć taki wynik:

ID     Name      SomeColumn

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

To nie zadziała (wiele wyników w zapytaniu podrzędnym):

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

Jest to trywialny problem, jeśli wykonuję przetwarzanie po stronie klienta. Ale to oznacza, że będę musiał uruchamiać zapytania X na każdej stronie, gdzie X jest liczbą wyników TableA.

Zauważ, że nie mogę po prostu zrobić grupy przez lub coś podobnie, ponieważ zwróci wiele wyników dla wierszy TableA.

Nie jestem pewien, czy UDF, wykorzystujący COALESCE lub coś podobnego może działać?

Author: Mark, 2008-09-21

10 answers

Nawet to będzie służyć celowi

Przykładowe dane

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'

Query:

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

Wyjście:

ID  Name    SomeColumn
1   ABC     X,Y,Z
2   MNO     R,S
 135
Author: priyanka.sarkar,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-08-19 16:28:12

1. Utwórz 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. Użycie w subquery:

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

3. Jeśli używasz procedury składowanej, możesz to zrobić w następujący sposób:

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
Author: Donnie Thomas,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-01-10 09:53:37

Myślę, że jesteś na dobrej drodze z COALESCE. Zobacz tutaj przykład budowania łańcucha rozdzielanego przecinkami:

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

 11
Author: Ben Hoffstein,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-09-21 16:22:19

W MySQL znajduje się funkcja group_concat , która zwróci to, o co prosisz.

SELECT TableA.ID, TableA.Name, group_concat(TableB.SomeColumn) 
as SomColumnGroup FROM TableA LEFT JOIN TableB ON 
TableB.TableA_ID = TableA.ID
 11
Author: Jacob,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-09-21 16:30:31

Być może będziesz musiał podać więcej szczegółów, aby uzyskać bardziej precyzyjną odpowiedź.

Ponieważ twój zbiór danych wydaje się trochę wąski, możesz rozważyć użycie wiersza na wynik i wykonanie przetwarzania końcowego u klienta.

Więc jeśli naprawdę chcesz, aby serwer wykonał pracę, zwróć wynik taki jak

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

Co oczywiście jest prostym połączeniem wewnętrznym NA ID

Po przywróceniu resultset w kliencie, zachowaj zmienną o nazwie CurrentName i użyj tego jako wyzwalacz, kiedy przestać zbierać SomeColumn do przydatnej rzeczy, którą chcesz zrobić.

 0
Author: Bill,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-09-21 16:26:41

Zakładając, że masz tylko klauzule WHERE w tabeli A, Utwórz procedurę składowaną w ten sposób:

SELECT Id, Name From tableA WHERE ...

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

Następnie wypełnij zestaw danych ds z nim. Then

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

Na końcu możesz dodać repeater na stronie, który umieszcza przecinki dla każdej linii

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

W ten sposób zrobisz to po stronie klienta, ale tylko z jednym zapytaniem, przekazując minimalne dane między bazą danych a frontend

 0
Author: Sklivvz,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-09-21 16:42:41

Próbowałem rozwiązania priyanka.Sarkar wspomniał i nie do końca udało się go uruchomić, jak prosiła operacja. Oto rozwiązanie, z którym skończyłem:

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
Author: mrogunlana,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-06-24 00:11:45

Rozwiązanie poniżej:

SELECT GROUP_CONCAT(field_attr_best_weekday_value)as RAVI
FROM content_field_attr_best_weekday LEFT JOIN content_type_attraction
    on content_field_attr_best_weekday.nid = content_type_attraction.nid
GROUP BY content_field_attr_best_weekday.nid

Użyj tego, możesz również zmienić połączenia

 -1
Author: ravi,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-07-13 18:10:51
SELECT t.ID, 
       t.NAME, 
       (SELECT t1.SOMECOLUMN 
        FROM   TABLEB t1 
        WHERE  t1.F_ID = T.TABLEA.ID) 
FROM   TABLEA t; 

Będzie to działać przy wybraniu z innej tabeli przy użyciu zapytania podrzędnego.

 -1
Author: ATHAR,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-10-21 07:46:26

Przejrzałem wszystkie odpowiedzi. Myślę, że wstawianie do bazy danych powinno wyglądać tak:

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

Przecinek powinien znajdować się na poprzednim końcu i przeszukiwać według %,X,%

 -1
Author: rsda,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-10-29 11:54:15