I have the following table:
Code Ref Value
A1 Car A
A1 Car -
A1 Car B
B2 Truck CC
B2 Truck D
B2 Truck -
C3 Van E
C3 Van F
C3 Van -
C3 Van G
The goal I am trying to accomplish, is a concatenated string grouping all of the values together like this:
Code Ref Value
A1 Car A-B
B2 Truck CCD-
C3 Van EF-G
I went off of the example here, but got nowhere. Here is what I came up with:
SELECT [Table].[Code]
, [Table].[Ref]
, STUFF((SELECT DISTINCT [Value]
FROM [Table2]
FOR XML PATH ('')),1, 1,'') AS Values
FROM [Table]
LEFT JOIN [Table2] ON
[Table2].[Code] = [Table].[Code]
Where am I going wrong? Is there a more efficient way to do this?
You have nothing linking your inner and outer references to [Table]
, and you also need to make the outer reference distinct. Finally you need to either have no column name within your subquery, or it needs to be [text()]
SELECT [Code]
,[Ref]
,STUFF((SELECT DISTINCT [Value] AS [text()]
FROM [Table] AS T2
WHERE T1.Code = T2.Code -- LINK HERE
AND T2.Ref = T2.Ref -- AND HERE
FOR XML PATH ('')
),1, 1,'') AS [Values]
FROM [Table] AS T1
GROUP BY T1.Code, T1.Ref; -- GROUP BY HERE
As an aside, you do not need to use STUFF
as you have no delimiter, STUFF
is typically used to remove the chosen delimiter from the start of the string. So when you have a string like ,value1,value2,value3
, STUFF(string, 1, 1, '')
will replace the first character with ''
leaving you with value1,value2,value3
.
You should also use the value
xquery method to ensure you are not tripped up by special characters, if you don't and you try an concatenate ">>"
and "<<"
you would not end up with ">><<"
as you might want, you would get ">><<"
, so a better query would be:
SELECT t1.Code,
t1.Ref,
[Values] = (SELECT DISTINCT [text()] = [Value]
FROM [Table] AS t2
WHERE T1.Code = T2.Code
AND T2.Ref = T2.Ref
FOR XML PATH (''), TYPE
).value('.', 'NVARCHAR(MAX)')
FROM [Table] AS T1
GROUP BY t1.Code, t1.Ref;
ADDENDUM
Based on the latest edit to the question it appears as though your Value
column is coming from another table, linked to the first table by Code
. If anything this makes your query simpler. You don't need the JOIN
, but you still need to make sure that there is an expression to link the outer table to the inner table your subquery. I am assuming that the rows are unique in the first table, so you probably don't need the group by either:
SELECT t1.Code,
t1.Ref,
[Values] = (SELECT DISTINCT [text()] = t2.[Value]
FROM [Table2] AS t2
WHERE T1.Code = T2.Code
FOR XML PATH (''), TYPE
).value('.', 'NVARCHAR(MAX)')
FROM [Table] AS T1;
WORKING EXAMPLE
CREATE TABLE #Table1 (Code CHAR(2), Ref VARCHAR(10));
INSERT #Table1 VALUES ('A1', 'Car'), ('B2', 'Truck'), ('C3', 'Van');
CREATE TABLE #Table2 (Code CHAR(2), Value VARCHAR(2));
INSERT #Table2
VALUES ('A1', 'A'), ('A1', '-'), ('A1', 'B'),
('B2', 'CC'), ('B2', 'D'), ('B2', '-'),
('C3', 'F'), ('C3', '-'), ('C3', 'G');
SELECT t1.Code,
t1.Ref,
[Values] = (SELECT DISTINCT [text()] = t2.[Value]
FROM #Table2 AS t2
WHERE T1.Code = T2.Code
FOR XML PATH (''), TYPE
).value('.', 'NVARCHAR(MAX)')
FROM #Table1 AS T1;