Replace comma separated master data with description in a column - sql

There are 2 SQL Server tables:
Products:
Name Status Code
------------------------------------
Product 1 1001, 1003
Product 2 1001, 1005, 1006
Status:
Code Description
------------------------------------
1001 State A
1003 State B
1005 State C
1006 State D
...
I wish to get something like:
Product Status
---------------------------------------------
Product 1 State A, State B
Product 2 State A, State C, State D

You can use a query like below:
See working demo
create table Products (Name varchar(100), [Status Code] varchar(100));
insert into Products values
('Product 1', '1001, 1003')
,('Product 2', '1001, 1005, 1006');
create table [Status] (Code varchar(100), Description varchar(100));
insert into [Status] values
('1001', 'State A')
,('1003', 'State B')
,('1005', 'State C')
,('1006', 'State D')
; WITH X AS
(
SELECT
P1.Name,
S.Description
FROM
(
SELECT *,
cast('<X>'+replace(P.[Status Code],',','</X><X>')+'</X>' as XML) AS xmlprods FROM Products P
)P1
CROSS APPLY
(
SELECT fdata.D.value('.','varchar(100)') AS splitdata
FROM P1.xmlprods.nodes('X') AS fdata(D)) O
LEFT JOIN [Status] S
ON S.Code= LTRIM(RTRIM(O.splitdata ))
)
SELECT
Name,
Description= STUFF((
SELECT ',' + Description FROM x AS x2
WHERE x2.Name = x.Name
ORDER BY Name FOR XML PATH,
TYPE).value(N'.[1]',N'varchar(max)'), 1, 1, '')
FROM
X
GROUP BY Name

You can try this. I used a temporary table but you can use any means you want
SELECT p.Product , p.Status , s.Description INTO #tmp FROM (
SELECT Name Product, TRIM(value ) Status FROM tblProduct CROSS
APPLY STRING_SPLIT(TRIM(StatusCode), ',') ) p JOIN tblStatus s ON
s.Code = p.Status
select distinct Product
, stuff((
select ',' + tmp2.Description
from #tmp tmp2
where tmp2.Product = tmp1.Product
order by tmp2.Product
for xml path('')
) ,1,1,'') as StatusCode from #tmp tmp1 group by Product

Below Query will help to make any comma separated to list.
SELECT A.OtherID,
Split.a.value('.', 'VARCHAR(100)') AS Data
FROM
(
SELECT OtherID,
CAST ('<M>' + REPLACE(Data, ',', '</M><M>') + '</M>' AS XML) AS Data
FROM Table1
) AS A CROSS APPLY Data.nodes ('/M') AS Split(a)

Related

Combine Multi Rows with COALESCE

Using SQL-Server 2012
I have the following Table:
Id Description
6192 Salzburg
6193 Salzburg
6194 Salzburg
6196 Innsbruck
6197 Innsbruck
6198 Innsbruck
6199 Innsbruck
6201 Bregenz
6202 Bregenz
6203 Bregenz
I want to Select each Distinct "Description" with all the Id's together in one string:
Description Ids
Salzburg '6192,6193,6194'
Innsbruck '6196,6197,6198'
I saw some similar code on this site [How to concatenate text from multiple rows into a single text string in SQL server?, but I couldn't figure it out yet for my purpose (don't want to use XML Path!). Here is what I have tried so far:
DECLARE #ids AS Nvarchar(MAX)
SELECT #ids = COALESCE(#ids + ',', '') + CAST(t.Id AS nvarchar(5))
FROM (SELECT tmp.Id FROM (SELECT id, [Description] FROM tblMasterPropValues WHERE IdCategory = 253 AND IsActive = 1) as tmp
WHERE [Description] = tmp.[Description]) AS t
SELECT #ids
--SELECT DISTINCT [Description], #ids AS IDs FROM tblMasterPropValues WHERE IdCategory = 253 AND IsActive = 1 AND Id IN (#ids)
I can't really get my head around it, and would appreciate any help on it.
You can try using STUFF() function
SELECT description, Ids = STUFF(
(SELECT ',' + Id
FROM tblMasterPropValues t1
WHERE t1.description = t2.description
FOR XML PATH (''))
, 1, 1, '') from tblMasterPropValues t2
group by description;
For that FOR XML PATH() is the right clause so, you can do :
SELECT DISTINCT v.description, STUFF(v1.ids, 1, 1, '''') + ''''
FROM tblMasterPropValues v CROSS APPLY
(SELECT ', '+ CAST(v1.Id AS VARCHAR(255))
FROM tblMasterPropValues v1
WHERE v1.description = v.description
FOR XML PATH('')
) v1(ids);
You can also make it by using recursive CTE
DECLARE #tblMasterPropValues TABLE (Id INT, Description VARCHAR(20))
INSERT INTO #tblMasterPropValues VALUES
(6192 , 'Salzburg'),
(6193 , 'Salzburg'),
(6194 , 'Salzburg'),
(6196 , 'Innsbruck'),
(6197 , 'Innsbruck'),
(6198 , 'Innsbruck'),
(6199 , 'Innsbruck'),
(6201 , 'Bregenz'),
(6202 , 'Bregenz'),
(6203 , 'Bregenz')
;WITH Tbl AS
(
SELECT
*,
ROW_NUMBER() OVER(PARTITION BY Description ORDER BY Id) AS RN,
COUNT(*) OVER(PARTITION BY Description) AS CNT
FROM #tblMasterPropValues
)
, Rcr AS (
SELECT *, CAST(Id AS varchar(max)) Ids
FROM Tbl WHERE RN = 1
UNION ALL
SELECT T.*, Rcr.Ids + ',' + CAST(T.Id AS VARCHAR(10)) Ids
FROM Rcr
INNER JOIN Tbl T ON T.RN = Rcr.RN + 1 and Rcr.Description = T.Description
)
SELECT RN, Description, Ids FROM Rcr
WHERE RN = CNT
Result:
Description Ids
-------------------- -----------------------
Salzburg 6192,6193,6194
Innsbruck 6196,6197,6198,6199
Bregenz 6201,6202,6203
Try this:
DECLARE #Table TABLE(ID INT, Description VARCHAR(25))
INSERT INTO #Table
VALUES (6192,'Salzburg' )
,(6193,'Salzburg' )
,(6194,'Salzburg' )
,(6196,'Innsbruck')
,(6197,'Innsbruck')
,(6198,'Innsbruck')
,(6199,'Innsbruck')
,(6201,'Bregenz' )
,(6202,'Bregenz' )
,(6203,'Bregenz' )
Query:
SELECT DISTINCT T2.Description,
SUBSTRING(
(
SELECT ','+CAST(T1.ID AS VARCHAR) AS [text()]
FROM #Table T1
WHERE T1.Description = T2.Description
ORDER BY T1.Description
FOR XML PATH ('')
), 2, 1000) [Ids]
FROM #Table T2
Result:
Description Ids
Bregenz 6201,6202,6203
Innsbruck 6196,6197,6198,6199
Salzburg 6192,6193,6194

How to join more than two tables on the basis of two parameters?

I have three tables #temp, tbProducts and tbVendor
tbVendor(States, AgentId, Products)
tbProduct(ProductId, ProductName)
#temp(ProductName)
SAMPLE DATA
tbVendor
-------------------------------- ----------- --------------------
States AgentId Products
-------------------------------- ----------- --------------------
Alabama,New York 1 T.V, Desktops
New Jersy, Florida 2 Cellphones, Laptops
New York, San Fransico 1 Cellphones, Desktop
New Jersy, San Fransico 1 A.C, Heaters
tbProduct
----------- -------------
ProductId ProductName
----------- -------------
1 T.V
2 Laptops
3 Desktop
4 Cellphones
5 A.C
6 Heaters
#temp
---------------
ProductName
---------------
T.V
Laptops
Desktop
Cellphones
A.C
Heaters
Now I have perform join operation on them in order to fetch ProductId and ProductName
Assigned tbVendor on the basis Agent Id and States fields.
For E.g I have fetch all the Products with their Names and Ids in New york with AgentId = 1 the output should be like
ProductId ProductName
----------- -------------
1 T.V
3 Desktop
4 Cellphones
Note that #Temp contains all the products assigned to AgentId = 1. Somehow I managed to fetch all the products assigned to AgentId = 1 and them in #temp tables. Now I am not able manage to fetch the output like i.e only the products assigned to New York The expected output is like below
ProductId ProductName
----------- -------------
1 T.V
3 Desktop
4 Cellphones
I have tried below lines of code bit it doesnot work
Select * from tbProduct L
JOIN #Temp TL ON L.ProductName collate SQL_Latin1_General_CP1_CI_AS = TL.ProductName
JOIN tbVendor Li ON Li.AgentId = #AgentId and Li.States like #States;
Note that #States contains New York and #AgentId contains 1.
Write as:
;WITH cte AS (
SELECT
AgentId,
CAST('<r>' + REPLACE(States, ',', '</r><r>') + '</r>' AS XML) AS States,
CAST('<r>' + REPLACE(Products, ',', '</r><r>') + '</r>' AS XML) AS Products
FROM #tbVendor
)
,FinalList AS (
SELECT
AgentId,
RTRIM(LTRIM (sTable.sColumn.value('.', 'VARCHAR(MAX)'))) AS States,
RTRIM(LTRIM (PTable.PColumn.value('.', 'VARCHAR(MAX)'))) AS Products
FROM cte
CROSS APPLY States.nodes('//r') AS sTable(sColumn)
CROSS APPLY Products.nodes('//r') AS PTable(PColumn)
)
SELECT DISTINCT F.Products AS ProductName
,T.ProductId AS ProductId
FROM FinalList F
CROSS APPLY (SELECT ProductId FROM #tbProduct TP WHERE TP.ProductName = F.Products) AS T
WHERE F.States = 'New York'
AND F.AgentId = 1
ORDER BY T.ProductId ASC
UPDATE: To deal with special character LIKE & REPLACE it WITH & as:
;WITH cte AS (
SELECT
AgentId,
CAST('<r>' + REPLACE(States, ',', '</r><r>') + '</r>' AS XML) AS States,
CAST('<r>' + REPLACE(REPLACE(Products,'&','&'), ',', '</r><r>') + '</r>' AS XML) AS Products
FROM #tbVendor
)
,FinalList AS (
SELECT
AgentId,
RTRIM(LTRIM (sTable.sColumn.value('.', 'VARCHAR(MAX)'))) AS States,
RTRIM(LTRIM (PTable.PColumn.value('.', 'VARCHAR(MAX)'))) AS Products
FROM cte
CROSS APPLY States.nodes('//r') AS sTable(sColumn)
CROSS APPLY Products.nodes('//r') AS PTable(PColumn)
)
SELECT DISTINCT F.Products AS ProductName
,T.ProductId AS ProductId
FROM FinalList F
CROSS APPLY (SELECT ProductId FROM #tbProduct TP WHERE TP.ProductName = F.Products) AS T
WHERE F.States = 'New York'
AND F.AgentId = 1
ORDER BY T.ProductId ASC
DEMO
TRY THIS:
DECLARE #state varchar(25) = 'New York',
#agentId int = 1
SELECT STUFF((SELECT ', ' + Products
FROM tbVendor tv
WHERE tv.AgentId = #agentId AND tv.States Like '%' +#state + '%'
FOR XML PATH('')), 1, 2, '') AS products
INTO #tmp
;with tmp(product, products) as (
select LTRIM(LEFT(products, CHARINDEX(', ',products+', ')-1)),
STUFF(products, 1, CHARINDEX(', ',products+', '), '')
from #tmp
union all
select LTRIM(LEFT(products, CHARINDEX(', ',products+', ')-1)),
STUFF(products, 1, CHARINDEX(', ',products+', '), '')
from tmp
where products > ''
)
SELECT tp.*
FROM tbProduct tp
INNER JOIN tmp t ON t.product = tp.ProductName
Split the CSV into rows
;WITH CTE AS
(
-- Split States
SELECT ROW_NUMBER() OVER(ORDER BY (SELECT(0))) RNO,
AgentId,
LTRIM(RTRIM(Split.a.value('.', 'VARCHAR(100)'))) 'STATE'
FROM
(
-- Use 3 REPLACE for '|', ';', ','
SELECT AgentId,
CAST ('<M>' + REPLACE([STATE], ',', '</M><M>') + '</M>' AS XML) AS Data
FROM #tbVendor
) AS A
CROSS APPLY Data.nodes ('/M') AS Split(a)
)
SELECT C1.AGENTID,C1.[STATE],TAB.Products,P.ProductID
FROM CTE C1
JOIN
(
-- Split Products
SELECT ROW_NUMBER() OVER(ORDER BY (SELECT(0))) RNO, AgentId,
LTRIM(RTRIM(Split.A.value('.', 'VARCHAR(100)'))) 'Products'
FROM
(
-- Use 3 REPLACE for '|', ';', ','
SELECT AgentId,
CAST ('<M>' + REPLACE(Products, ',', '</M><M>') + '</M>' AS XML) AS Data
FROM #tbVendor
) AS A
CROSS APPLY Data.nodes ('/M') AS Split(a)
)TAB
ON C1.RNO=TAB.RNO AND C1.AGENTID=TAB.AGENTID
-- Get Product Id
JOIN #tbProduct P
ON TAB.Products=P.ProductName
WHERE ...your conditions...
Now you will get all states with ProductId, ProductName and AgentId
SQL FIDDLE

how to select in 3 table in sql

I have created 3 table
table 1 "Sale" that saved date of user sale
table 2 "ProductFactor" that saved factorid and productid in wich factoreid
tabel 3 "Product" that saved productid and product name
I want select in 3 table for this result:
show user factorid +price+ saledate + any product name that avalibe in this factorid
but when do it, for example when in one factorid that have 3 productid, is show this:
date factoreid name price
2013-09-25 1 1 a 2000
2013-09-25 1 1 b 3000
2013-09-25 2 2 c 4000
2013-09-25 3 3 d 3500
2013-09-25 1 1 e 8000
I want show this:
date factoreid name price sumprice
2013-09-25 1 1 a,b,e a price,b price, c price sum of this 3 product name
2013-09-25 2 2 c 4000
2013-09-25 3 3 d 3500 my code is:
CREATE PROCEDURE [dbo].[GetUserSaleReport]
#CurrentUserId uniqueidentifier
AS BEGIN
SELECT dbo.Sale.SaleDate,
dbo.ProductFactor.FactoreId,
dbo.Product.ProductName,
dbo.Product.Price
FROM Sale
INNER JOIN ProductFactor
ON dbo.Sale.FactoreId=dbo.ProductFactor.FactoreId
INNER JOIN dbo.Product
ON dbo.ProductFactor.ProductId=dbo.Product.ProductId
WHERE dbo.Sale.UserId = #CurrentUserId
AND dbo.Sale.FactoreId=dbo.ProductFactor.FactoreId
AND dbo.ProductFactor.ProductId=dbo.Product.ProductId
ORDER BY dbo.Sale.SaleDate
END
I dont have all three tables but assuming all this data was coming from one table you could do something like this... You can apply the same login after you have joined all the tables and have got all the required data in one place
SELECT DISTINCT [DATE], Factoreid, STUFF(T2.NameList, 1, 2, '') AS name, STUFF(T3.PriceList, 1, 2, '') AS price, SUM(Price) PriceSUM
FROM TableName t
OUTER APPLY (
SELECT ', ' + name [text()]
FROM TableName
WHERE Factoreid = t.Factoreid
FOR XML PATH('')
) T2(NameList)
OUTER APPLY (
SELECT ', ' + CAST(price AS VARCHAR) [text()]
FROM TableName
WHERE Factoreid = t.Factoreid
FOR XML PATH('')
) T3(PriceList)
GROUP BY [DATE], Factoreid, STUFF(T2.NameList, 1, 2, ''), STUFF(T3.PriceList, 1, 2, '')
I have tried tweaked the code I think it will work try this
CREATE PROCEDURE [dbo].[GetUserSaleReport]
#CurrentUserId uniqueidentifier
AS BEGIN
SET NOCOUNT ON;
IF OBJECT_ID('tempdb..#Temptable') IS NOT NULL
DROP TABLE #Temptable
SELECT dbo.Sale.SaleDate AS [DATE],
dbo.ProductFactor.FactoreId AS Factoreid,
dbo.Product.ProductName AS Name,
dbo.Product.Price AS Price
INTO #Temptable
FROM Sale
INNER JOIN ProductFactor
ON dbo.Sale.FactoreId=dbo.ProductFactor.FactoreId
INNER JOIN dbo.Product
ON dbo.ProductFactor.ProductId=dbo.Product.ProductId
WHERE dbo.Sale.UserId = #CurrentUserId
AND dbo.Sale.FactoreId=dbo.ProductFactor.FactoreId
AND dbo.ProductFactor.ProductId=dbo.Product.ProductId
ORDER BY dbo.Sale.SaleDate
SELECT DISTINCT [DATE], Factoreid, STUFF(T2.NameList, 1, 2, '') AS name, STUFF(T3.PriceList, 1, 2, '') AS price, SUM(Price) PriceSUM
FROM #Temptable t
OUTER APPLY (
SELECT ', ' + Name [text()]
FROM #Temptable
WHERE Factoreid = t.Factoreid
FOR XML PATH('')
) T2(NameList)
OUTER APPLY (
SELECT ', ' + CAST(price AS VARCHAR) [text()]
FROM #Temptable
WHERE Factoreid = t.Factoreid
FOR XML PATH('')
) T3(PriceList)
GROUP BY [DATE], Factoreid, STUFF(T2.NameList, 1, 2, ''), STUFF(T3.PriceList, 1, 2, '')
IF OBJECT_ID('tempdb..#Temptable') IS NOT NULL
DROP TABLE #Temptable
SET NOCOUNT OFF;
END

showing rows of table as columns based on some ID

I have a table like
ID option
1 optionA
1 optionB
1 optionC
1 optionD
And I want a result like:
ID A B C D
1 optionA optionB optionC optionD
What is the best way to do this?
Query which i have tried is
select * from TableName PIVOT (option for ID = 2674 )) as abc
this will not work since PIVOT expects aggregated function..
I have also tried COALESCE like this
declare #t table(num VARCHAR(100))
insert into #t
select choice FROM QuestionAnswers where QuestionID=2674
select num from #t
declare #s varchar(8000)
select #s = COALESCE(#s + ',', '') + num
from #t
exec('select '+#s)
but this doesn't work as well..
This type of data transformation is known as a pivot. In SQL Server 2005+ there is a function that will perform this data rotation for you. However, there are many ways that you can perform this data transformation.
Here is a PIVOT query that will work with your sample data:
select *
from
(
select id, [option], right([option], 1) col
from yourtable
) src
pivot
(
max([option])
for col in (a, b, c, d)
) piv
See SQL Fiddle with Demo.
This can also be performed using an aggregate function with a CASE expression:
select id,
max(case when col = 'a' then [option] else null end) a,
max(case when col = 'b' then [option] else null end) b,
max(case when col = 'c' then [option] else null end) c,
max(case when col = 'd' then [option] else null end) d
from
(
select id, [option], right([option], 1) col
from yourtable
) src
group by id
See SQL Fiddle with Demo.
You can perform multiple joins on your table:
select a.id,
a.[option] a,
b.[option] b,
c.[option] c,
d.[option] d
from yourtable a
left join yourtable b
on a.id = b.id
and right(b.[option], 1) = 'b'
left join yourtable c
on a.id = c.id
and right(c.[option], 1) = 'c'
left join yourtable d
on a.id = d.id
and right(d.[option], 1) = 'd'
where right(a.[option], 1) = 'a'
See SQL Fiddle with Demo
Lastly, this can be done using dynamic sql if the values to be turned into columns is unknown:
DECLARE #colsName AS NVARCHAR(MAX),
#cols AS NVARCHAR(MAX),
#query AS NVARCHAR(MAX)
select #colsName = STUFF((SELECT distinct ', ' + QUOTENAME(right([option], 1)) +' as '+ right([option], 1)
from yourtable
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)')
,1,1,'')
select #cols = STUFF((SELECT distinct ', ' + QUOTENAME(right([option], 1))
from yourtable
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)')
,1,1,'')
set #query = 'SELECT id, ' + #colsName + ' from
(
select id, [option], right([option], 1) col
from yourtable
) x
pivot
(
max([option])
for col in (' + #cols + ')
) p '
execute(#query)
See SQL Fiddle with Demo
The result of all queries is:
| ID | A | B | C | D |
----------------------------------------------
| 1 | optionA | optionB | optionC | optionD |
CREATE TABLE Product(Cust VARCHAR(25), Product VARCHAR(20), QTY INT)
GO
-- Inserting Data into Table
INSERT INTO Product(Cust, Product, QTY)
VALUES('KATE','VEG',2)
INSERT INTO Product(Cust, Product, QTY)
VALUES('KATE','SODA',6)
INSERT INTO Product(Cust, Product, QTY)
VALUES('KATE','MILK',1)
INSERT INTO Product(Cust, Product, QTY)
VALUES('KATE','BEER',12)
INSERT INTO Product(Cust, Product, QTY)
VALUES('FRED','MILK',3)
INSERT INTO Product(Cust, Product, QTY)
VALUES('FRED','BEER',24)
INSERT INTO Product(Cust, Product, QTY)
VALUES('KATE','VEG',3)
GO
-- Selecting and checking entires in table
SELECT *
FROM Product
GO
-- Pivot Table ordered by PRODUCT
SELECT PRODUCT, FRED, KATE
FROM (
SELECT CUST, PRODUCT, QTY
FROM Product) up
PIVOT (SUM(QTY) FOR CUST IN (FRED, KATE)) AS pvt
ORDER BY PRODUCT
GO
-- Pivot Table ordered by CUST
SELECT CUST, VEG, SODA, MILK, BEER, CHIPS
FROM (
SELECT CUST, PRODUCT, QTY
FROM Product) up
PIVOT (SUM(QTY) FOR PRODUCT IN (VEG, SODA, MILK, BEER, CHIPS)) AS pvt
ORDER BY CUST
GO
-- Unpivot Table ordered by CUST
SELECT CUST, PRODUCT, QTY
FROM
(
SELECT CUST, VEG, SODA, MILK, BEER, CHIPS
FROM (
SELECT CUST, PRODUCT, QTY
FROM Product) up
PIVOT
( SUM(QTY) FOR PRODUCT IN (VEG, SODA, MILK, BEER, CHIPS)) AS pvt) p
UNPIVOT
(QTY FOR PRODUCT IN (VEG, SODA, MILK, BEER, CHIPS)
) AS Unpvt
GO
-- Clean up database
DROP TABLE Product
GO
Ref http://blog.sqlauthority.com/2008/06/07/sql-server-pivot-and-unpivot-table-examples/
Edited
DECLARE #Product TABLE (ID int, _option varchar(10) )
-- Inserting Data into Table
INSERT INTO #Product
(
ID,
_option
)
SELECT 1, 'optionA' UNION ALL
SELECT 1, 'optionB' UNION ALL
SELECT 1, 'optionC' UNION ALL
SELECT 1, 'optionD'
SELECT
optionA, optionB, optionC, optionD
FROM (
SELECT ID, _option
FROM #Product) up
PIVOT (SUM(ID) FOR _option IN (optionA, optionB, optionC, optionD)) AS pvt

Duplicates without using While or Cursor in T-SQL

ID Name
1 A
1 B
1 C
2 X
2 Y
3 P
3 Q
3 R
These are the columns in a table. I want to get output like
ID Company
1 A,B,C
2 X, Y
3 P,Q,R
Restriction is that I cannot use WHILE or CURSOR. Please write a query for the same.
This query should do it - uses FOR XML PATH which is new in SQL Server 2005 - hope you are on 2005 or higher, you didn't clearly specify.....
SELECT
ID,
STUFF(CAST((SELECT ','+Name FROM dbo.YourTable t2
WHERE t2.ID = dbo.YourTable.ID
FOR XML PATH(''), TYPE) AS VARCHAR(MAX)), 1, 1, '') AS 'Company'
FROM
dbo.YourTable
GROUP BY
ID
Here's a solution using the CROSS APPLY method:
select id, sub.names
from (
select distinct id from YourTable
) a
cross apply (
select name + ', ' as [text()]
from YourTable b
where b.id = a.id
for xml path('')
) sub(names)
For 2005 version:
CREATE TABLE dbo.TEST([Type] INTEGER, [Name] NVARCHAR(100), [Qty] INTEGER)
GO
INSERT dbo.TEST VALUES(1, N'a', 5)
INSERT dbo.TEST VALUES(1, N'b', 6)
INSERT dbo.TEST VALUES(2, N'c', 44)
INSERT dbo.TEST VALUES(3, N'd', 1)
GO
select [Type],
[Description] = replace((select [Name] + ':' + cast([Qty] as varchar) as 'data()'
from TEST where [Type] = t.[Type] for xml path('')), ' ', ',')
from dbo.TEST t
group by [Type]
go
drop table dbo.TEST
You can group on the ID to get the unique values, then get the comma separated string for each using a for xml query:
select
a.ID,
substring((
select ', ' + Name
from Test1
where Test1.ID = a.ID
for xml path('')
), 3, 1000) as Company
from
TheTable a
group by
a.ID