Combine varios resultados de una subconsulta en un único valor separado por comas

StackOverflow https://stackoverflow.com/questions/111341

  •  02-07-2019
  •  | 
  •  

Pregunta

Tengo dos mesas:

TableA
------
ID,
Name

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

La relación es una fila de TableA - muchos de TableB.

Ahora quiero ver un resultado como este:

ID     Name      SomeColumn

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

Esto no funcionará (varios resultados en una subconsulta):

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

Este es un problema trivial si hago el procesamiento en el lado del cliente.Pero esto significará que tendré que ejecutar X consultas en cada página, donde X es el número de resultados de TableA.

Tenga en cuenta que no puedo simplemente hacer GROUP BY o algo similar, ya que devolverá múltiples resultados para filas de TableA.

No estoy seguro de si una UDF, utilizar COALESCE o algo similar podría funcionar.

¿Fue útil?

Solución 2

1.Cree la 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.Usar en subconsulta:

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

3.Si está utilizando un procedimiento almacenado, puede hacer esto:

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

Otros consejos

Incluso esto servirá al propósito

Data de muestra

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'

Consulta:

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

Producción:

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

Creo que estás en el camino correcto con COALESCE.Consulte aquí un ejemplo de cómo crear una cadena delimitada por comas:

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

En MySQL hay un grupo_concat función que devolverá lo que estás pidiendo.

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

Es posible que deba proporcionar más detalles para obtener una respuesta más precisa.

Dado que su conjunto de datos parece un poco limitado, podría considerar simplemente usar una fila por resultado y realizar el posprocesamiento en el cliente.

Entonces, si realmente está buscando que el servidor haga el trabajo, devuelva un conjunto de resultados como

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

que por supuesto es una simple UNIÓN INTERNA en ID

Una vez que tenga el conjunto de resultados en el cliente, mantenga una variable llamada CurrentName y utilícela como disparador para dejar de recopilar SomeColumn en la cosa útil que desea que haga.

Suponiendo que solo tiene cláusulas WHERE en la tabla A, cree un procedimiento almacenado de la siguiente manera:

SELECT Id, Name From tableA WHERE ...

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

Luego llene un DataSet ds con él.Entonces

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

Finalmente puedes agregar un repetidor en la página que pone las comas para cada línea.

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

De esta manera lo harás del lado del cliente pero con una sola consulta, pasando un mínimo de datos entre la base de datos y el frontend.

Probé la solución que priyanka.sarkar mencionó y no logré que funcionara como me pidió el OP.Aquí está la solución con la que terminé:

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

Solución a continuación:

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

Utilice esto, también puede cambiar las uniones

SELECT t.ID, 
       t.NAME, 
       (SELECT t1.SOMECOLUMN 
        FROM   TABLEB t1 
        WHERE  t1.F_ID = T.TABLEA.ID) 
FROM   TABLEA t; 

Esto funcionará para seleccionar de una tabla diferente mediante una subconsulta.

He revisado todas las respuestas.Creo que la inserción de la base de datos debería ser como:

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

La coma debe estar al final anterior y buscar por me gusta. %,X,%

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top