J'ai deux tables:
TableA
------
ID,
Name
TableB
------
ID,
SomeColumn,
TableA_ID (FK for TableA)
La relation est une ligne de TableA
- beaucoup de TableB
.
Maintenant, je veux voir un résultat comme celui-ci:
ID Name SomeColumn
1. ABC X, Y, Z (these are three different rows)
2. MNO R, S
Cela ne fonctionnera pas (plusieurs résultats dans une sous-requête):
SELECT ID,
Name,
(SELECT SomeColumn FROM TableB WHERE F_ID=TableA.ID)
FROM TableA
C'est un problème trivial si je traite le client. Mais cela signifiera que je devrai exécuter X requêtes sur chaque page, où X est le nombre de résultats de TableA
.
Notez que je ne peux pas simplement faire un GROUP BY ou quelque chose de similaire, car cela retournera plusieurs résultats pour les lignes de TableA
.
Je ne sais pas si une FDU utilisant COALESCE ou quelque chose de similaire peut fonctionner?
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
SELECT ID, Name, dbo.CombineValues(FK_ID) FROM TableA
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
Même cela servira le but
échantillon de données
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'
Requête:
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
Sortie:
ID Name SomeColumn
1 ABC X,Y,Z
2 MNO R,S
Je pense que vous êtes sur la bonne voie avec COALESCE. Voir ici pour un exemple de construction d'une chaîne délimitée par des virgules:
http://www.sqlteam.com/article/using-coalesce-to-build-comma-delimited-string
Dans MySQL, il existe une fonction group_concat qui retournera ce que vous demandez.
SELECT TableA.ID, TableA.Name, group_concat(TableB.SomeColumn)
as SomColumnGroup FROM TableA LEFT JOIN TableB ON
TableB.TableA_ID = TableA.ID
En supposant que vous n’ayez que des clauses WHERE sur la table A, créez une procédure stockée ainsi:
SELECT Id, Name From tableA WHERE ...
SELECT tableA.Id AS ParentId, Somecolumn
FROM tableA INNER JOIN tableB on TableA.Id = TableB.F_Id
WHERE ...
Puis remplissez un DataSet ds avec. ensuite
ds.Relations.Add("foo", ds.Tables[0].Columns("Id"), ds.Tables[1].Columns("ParentId"));
Enfin, vous pouvez ajouter un répéteur dans la page qui met les virgules pour chaque ligne
<asp:DataList ID="Subcategories" DataKeyField="ParentCatId"
DataSource='<%# Container.DataItem.CreateChildView("foo") %>' RepeatColumns="1"
RepeatDirection="Horizontal" ItemStyle-HorizontalAlign="left" ItemStyle-VerticalAlign="top"
runat="server" >
De cette façon, vous le ferez côté client mais avec une seule requête, en transmettant un minimum de données entre la base de données et le client.
J'ai essayé la solution mentionnée par priyanka.sarkar et elle n'a pas très bien fonctionné comme l'a demandé l'OP. Voici la solution avec laquelle je me suis retrouvé:
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
Vous devrez peut-être fournir plus de détails pour une réponse plus précise.
Étant donné que votre ensemble de données semble assez étroit, vous pouvez envisager d'utiliser simplement une ligne par résultat et d'effectuer le post-traitement sur le client.
Donc, si vous cherchez vraiment à faire en sorte que le serveur fasse le travail, renvoyez un résultat comme
ID Name SomeColumn
1 ABC X
1 ABC Y
1 ABC Z
2 MNO R
2 MNO S
qui est bien sûr un simple INNER JOIN on ID
Une fois que vous avez le jeu de résultats chez le client, gérez une variable appelée CurrentName et utilisez-la comme déclencheur pour cesser de collecter SomeColumn dans la tâche utile que vous souhaitez faire.