Combine varios resultados de una subconsulta en un único valor separado por comas
-
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.
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,%