'Ordering comma separated column values from related tables in SQL server

I am using SQL server. I would like to have a query for below mentioned requirement. I am at Beginner level in SQL I have two tables as shown below:

Table: Car

Id CarName Company LaunchYear
1 Audi Q7 Audi 2022
2 Ford GT Ford 2021

Table: CarType

TypeId CarId Colour PetrolRate DieselRate ElectricRate
1 1 PLATINUM 10000 9000 11000
2 1 GOLD 9500 8500 10500
3 1 SILVER 9250 8250 10250

I require the output in a single row for unique car.

It must have comma separated values of rates based on their colours.

The value of colours must be ordered by alphabetically ascending and the rates must be aligned with the colours.

I tried below query but I am getting multiple rows for a single car:

select * 
from Car c
left join CarType ct on ct.CarId= c.Id
where c.Id = 1

Please refer below required output:

Output

CarId CarName Company LaunchYear Colours PetrolRates DieselRates ElectricRates
1 Audi Q7 Audi 2022 GOLD,PLATINUM,SILVER 9500,10000,9250 8500,9000,8250 10500,11000,10250

Answer Acceptance Reason:

I have accepted the solution which uses XML PATH because I am having SQL Server 2016.

Note: String_AGG() is for SQL Server 2017 and higher versions. The solution listed with it is also appropriate. (Only one solution can be accepted as an answer :))



Solution 1:[1]

This is achievable using FOR XML PATH string function since sql server 2005

select t1.id, t1.CarName, t1.Company, t1.LaunchYear, t2.Colours, t2.PetrolRates, t2.DieselRates, t2.ElectricRates
from Car t1
inner join
    (select  CarId
       ,stuff((SELECT ', ' + cast(Colour AS varchar(50)) [text()]
         from CarType 
         where CarId = t.CarId
         for xml path(''), type)
        .value('.','NVARCHAR(MAX)'),1,2,' ') Colours
        ,stuff((SELECT ', ' + cast(PetrolRate AS varchar(50)) [text()]
         from CarType 
         where CarId = t.CarId
         for xml path(''), type)
        .value('.','NVARCHAR(MAX)'),1,2,' ') PetrolRates
        ,stuff((SELECT ', ' + cast(DieselRate AS varchar(50)) [text()]
         from CarType 
         where CarId = t.CarId
         for xml path(''), type)
        .value('.','NVARCHAR(MAX)'),1,2,' ') DieselRates
        ,stuff((SELECT ', ' + cast(ElectricRate AS varchar(50)) [text()]
         from CarType 
         where CarId = t.CarId
         for xml path(''), type)
        .value('.','NVARCHAR(MAX)'),1,2,' ') ElectricRates
    from CarType t
    group by CarId) as t2 on t2.CarId = t1.id

Solution 2:[2]

We can use STRING_AGG( ~ , ',') to make a comma seperated list with WITHIN GROUP (ORDER BY TypeId) to be sure that the different values are in the right order.

create table cars (id int, carName varchar(25), Company varchar(25), LaunchYear int)
insert into cars values (1,'Audo Q7','Audi',2022),(2,'Ford GT','Ford',2021);
create table carType(TypeId int,CarId   int,Colour  varchar(10),PetrolRate  int,DieselRate  int,ElectricRate int);
insert into carType values
(1, 1,  'PLATINUM',10000,9000,  11000),
(2, 1,  'GOLD'    ,9500 ,8500,  10500),
(3, 1,  'SILVER'  ,9250 ,8250,  10250);

select
  c.id,
  c.carName,
  c.Company,
  c.LaunchYear,
  string_agg( Colour ,',') WITHIN GROUP (ORDER BY TypeId) Colour,
  string_agg( PetrolRate,',') WITHIN GROUP (ORDER BY TypeId) PetrolRate,
  string_agg( DieselRate,',') WITHIN GROUP (ORDER BY TypeId) DieselRate,
  string_agg( ElectricRate,',') WITHIN GROUP (ORDER BY TypeId) ElectricRate
from cars c
left join carType t
on c.id = t.carID
group by
  c.id,
  c.carName,
  c.Company,
  c.LaunchYear
GO
 id | carName | Company | LaunchYear | Colour               | PetrolRate      | DieselRate     | ElectricRate     
 -: | :------ | :------ | ---------: | :------------------- | :-------------- | :------------- | :----------------
  1 | Audo Q7 | Audi    |       2022 | PLATINUM,GOLD,SILVER | 10000,9500,9250 | 9000,8500,8250 | 11000,10500,10250
  2 | Ford GT | Ford    |       2021 | null                 | null            | null           | null             
 

db<>fiddle here

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1
Solution 2 Larnu