There are a couple alternatives here, but here are some things to consider:
- Determine what you want your left-most item to be -- in this case, it looks like it's supposed to be
station. If that is the case, one way to approach it is to first get the distinct set of stations. This can be done using a group by or a distinct.
- Determine the level of the items for which you wish to generate a list -- in this case it's
client_code. Therefore, you want to get you inner select to be at that level. One way to do that is to resolve the distinct set of client codes prior to attempting to use for xml.
One critique -- it's always good to provide a simple set of data. Makes providing an answer much easier and faster.
Again, there are alternatives here, but here's a possible solution.
The test data
select top (100)
client_id = abs(checksum(newid())) % 100,
client_code = char(abs(checksum(newid())) % 10 + 65)
into #client
from sys.all_columns a
cross join sys.all_columns b;
select top (100)
station = abs(checksum(newid())) % 10,
client_id = abs(checksum(newid())) % 50 -- just a subset
into #temp
from sys.all_columns a
cross join sys.all_columns b;
The query
select station, client_codes = stuff((
select ', ' + cc.client_code
from (
select distinct c.client_code -- distinct client codes
from #temp t
join #client c
on t.client_id = c.client_id
where t.station = s.station) cc
order by client_code
for xml path('')), 1, 2, '')
from (
select distinct station
from #temp) s; -- distinct stations
The results
station client_codes
----------- ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
0 B, C, D, E, G, J
1 A, B, D, G, H, J
2 A, C, E, F, G, H, J
3 B, C, H, J
4 A, B, C, D, F, H, J
5 H, J
6 D, E, F, G, I
7 A, C, D, F, G, H, J
8 A, E, G
9 C, E, F, G, I
Hope this helps.