I have multiple rows of order data which i need to consolidate in one row per part.
An example is as follows:
OrderNum PartNum Qty
-------------------------------
1 24 2
2 25 10
3 24 5
4 24 10
This then needs to be consolidated into:
OrderNum PartNum Qty
-------------------------------
1, 3, 4 24 17
2 25 10
Does anybody have any ideas how I can do this?
I have had a look around online but cannot find a solution to this use case.
Many thanks in advance,
Try this
SELECT STUFF((SELECT ',' + CAST(OrderNum AS VARCHAR(4))
FROM mytable AS s
WHERE s.PartNum = t.PartNum
FOR XML PATH('')), 1, 1, '') AS OrderNum
PartNum, SUM(Qty)
FROM mytable AS t
GROUP BY PartNum
This can be done by grouping on PartNum, sum the quantities with SUM() and concatenating strings using FOR XML PATH('') in a correlated subquery. Using FOR XML PATH('') to concatenate string is explained in this answer on SO.
DECLARE #t TABLE(OrderNum INT, PartNum INT, Qty INT);
INSERT INTO #t(OrderNum,PartNum,Qty)
VALUES(1,24,2),(2,25,10),(3,24,5),(4,24,10);
SELECT
OrderNum=STUFF((
SELECT
','+CAST(i.OrderNum AS VARCHAR)
FROM
#t AS i
WHERE
i.PartNum=o.PartNum
FOR XML
PATH(''), TYPE
).value('.[1]','VARCHAR(MAX)'),1,1,''),
o.PartNum,
Qty=SUM(o.Qty)
FROM
#t AS o
GROUP BY
o.PartNum;
Result:
OrderNum | PartNum | Qty
------------------------
1,3,4 | 24 | 17
2 | 25 | 10
SQL Server 2016 added the STRING_AGG function.
In your case, you could write
select STRING_ACC(OrderId,','),PartNum, Sum(Qty)
from MyTable
Group by PartNum
For earlier versions you'd have to use one of the techniques described by Aaron Bertrand in Grouped Concatenation in SQL Server. The fastest is to use a SQLCLR method. Next comes the FOR XML method posted by #GiorgosBetsos
DECLARE #t TABLE(OrderNum INT, PartNum INT, Qty INT)
INSERT INTO #t VALUES(1 , 24 , 2)
INSERT INTO #t VALUES(2 , 25 , 10)
INSERT INTO #t VALUES(3 , 24 , 5)
INSERT INTO #t VALUES(4 , 24 , 10)
SELECT OrderNum =
STUFF((SELECT ', ' + CONVERT(VARCHAR(50),OrderNum)
FROM #t b
WHERE b.PartNum = a.PartNum
FOR XML PATH('')), 1, 2, ''),
PartNum,
SUM(Qty) as Qty
FROM #t a
GROUP BY PartNum
Result
There are many ways to do this.
create table tablename (Name varchar(100), Rnk int)
Insert into tablename values
('Northshore', 1),
('F3', 2),
('Borderline', 3),
('Mattoon',3),
('Vinemane',5),
('Arizona',5),
('WestShore', 5),
('Schumburg', 5),
('Wilson',5)
--Method2
Select distinct
names= REPLACE(
(
Select a.Name as [data()]
From tablename A
Where A.Rnk = b.Rnk
Order by a.Name
FOR XML PATH ('') ), ' ', ',') ,Rnk
From tablename B Order by Rnk
OR
CREATE TABLE TestTable (ID INT, Col VARCHAR(4))
GO
INSERT INTO TestTable (ID, Col)
SELECT 1, 'A'
UNION ALL
SELECT 1, 'B'
UNION ALL
SELECT 1, 'C'
UNION ALL
SELECT 2, 'A'
UNION ALL
SELECT 2, 'B'
UNION ALL
SELECT 2, 'C'
UNION ALL
SELECT 2, 'D'
UNION ALL
SELECT 2, 'E'
GO
SELECT *
FROM TestTable
GO
-- Get CSV values
SELECT t.ID, STUFF(
(SELECT ',' + s.Col
FROM TestTable s
WHERE s.ID = t.ID
FOR XML PATH('')),1,1,'') AS CSV
FROM TestTable AS t
GROUP BY t.ID
GO
OR
CREATE TABLE #mable(mid INT, token nvarchar(16))
INSERT INTO #mable VALUES (0, 'foo')
INSERT INTO #mable VALUES(0, 'goo')
INSERT INTO #mable VALUES(1, 'hoo')
INSERT INTO #mable VALUES(1, 'moo')
SELECT m1.mid,
( SELECT m2.token + ','
FROM #mable m2
WHERE m2.mid = m1.mid
ORDER BY token
FOR XML PATH('') ) AS token
FROM #mable m1
GROUP BY m1.mid ;
Also, see this.
http://blog.sqlauthority.com/2009/11/25/sql-server-comma-separated-values-csv-from-table-column/
Related
I have a table like this:
ID Type Score
-------------------
5 1 100
8 1 200
3 1 300
8 2 100
3 2 200
5 2 300
How do I sort them by descending score (to give them a ranking for that Type) and then create a table which a column for each Type where the ID's positions are shown such as:
ID Type1 Type2
--------------------
3 1st 2nd
5 3rd 1st
8 2nd 3rd
So far I am able able to do this by explicitly declaring the Type number such as:
SELECT ROW_NUMBER() OVER(ORDER BY Score DESC) AS Rank, ID
FROM Table
WHERE Type = 1
This returns a rank for each ID when Type is 1.
How do I join this together with the same result when Type is 2? And how do I do this for any number of types?
There are a number of ways to tackled this. My choice would be to use conditional aggregation. Here is how this might look. If you need a dynamic number of types that can be accomplished also but is a little trickier.
declare #Something table
(
ID int
, Type int
, Score int
)
;
insert #Something values
(5, 1, 100)
, (8, 1, 200)
, (3, 1, 300)
, (8, 2, 100)
, (3, 2, 200)
, (5, 2, 300)
;
with SortedValues as
(
select *
, RowNum = ROW_NUMBER() over (partition by Type order by Score)
from #Something
)
select ID
, Type1 = max(case when Type = 1 then RowNum end)
, Type2 = max(case when Type = 2 then RowNum end)
from SortedValues
group by ID
order by ID
;
-- EDIT --
I realized you said you need to have this work for any number of Types. Most people around SO like to ue a dynamic pivot. I personally find the syntax for pivot to be very obtuse. I prefer to build a dynamic version of conditional aggregation for this type of thing. Here is how you can use dynamic sql to generate the results for any number of Types.
Note I had to switch to using a temp table because a table variable would not be available in the scope of the dynamic sql unless it is declared inside the dynamic sql.
if OBJECT_ID('tempdb..#Something') is not null
drop table #Something
create table #Something
(
ID int
, Type int
, Score int
)
;
insert #Something values
(5, 1, 100)
, (8, 1, 200)
, (3, 1, 300)
, (8, 2, 100)
, (3, 2, 200)
, (5, 2, 300)
;
declare #StaticPortion nvarchar(2000) =
'with SortedValues as
(
select *, ROW_NUMBER() over(partition by Type order by Score) as RowNum
from #Something
)
select ID';
declare #DynamicPortion nvarchar(max) = '';
with E1(N) AS (select 1 from (values (1),(1),(1),(1),(1),(1),(1),(1),(1),(1))dt(n)),
E2(N) AS (SELECT 1 FROM E1 a, E1 b), --10E+2 or 100 rows
cteTally(N) AS
(
SELECT ROW_NUMBER() OVER (ORDER BY (SELECT NULL)) FROM E2
)
select #DynamicPortion = #DynamicPortion +
', MAX(Case when Type = ' + CAST(N as varchar(6)) + ' then RowNum end) as Type' + CAST(N as varchar(6)) + CHAR(10)
from cteTally t
where t.N <=
(
select Count(distinct Type)
from #Something
)
declare #FinalStaticPortion nvarchar(2000) = ' from SortedValues
group by ID
order by ID';
select #StaticPortion + #DynamicPortion + #FinalStaticPortion
declare #SqlToExecute nvarchar(max) = #StaticPortion + #DynamicPortion + #FinalStaticPortion;
select #SqlToExecute
exec sp_executesql #SqlToExecute
SQL Server 2012: How to find common values in a column
Please find below my exact requirement and help me with the Fine tuned query.
Please find below my exact requirement and help me with the Fine tuned query.
Please find below my exact requirement and help me with the Fine tuned query.
Input :
select 1, 'sankar', 'GROUPLG'
union all
select 1, 'sankar', 'GROUPLS'
union all
select 1, 'sankar', 'GROUPNG'
union all
select 1, 'sankar', 'GROUPNS'
union all
select 2, 'Srini', 'HYDRSPMLG'
union all
select 2, 'Srini', 'HYDRSPMLS'
union all
select 3, 'Ravi', 'AADSCLS'
union all
select 4, 'Arun', 'RREDFTLS'
union all
select 4, 'Arun', 'RREDFTNG'
union all
select 5, 'Raja', '1234567'
union all
select 5, 'Raja', 'ABCDESLS'
union all
select 5, 'Raja', 'ABCDESLG'
union all
select 6, 'Dhilip', 'GGGGRASCDW_RV'
Output :
-- 1 Sankar GROUP(LG,LS,NG,NS)
-- 2 Srini HYDRSPM(LG,LS)
-- 3 Ravi AADSCLS
-- 4 Arun RREDFT(LS,NG)
-- 5 Raja 1234567
-- 5 Raja ABCDESLG(LG,LS)
-- 6 dhilip GGGGRASCDW_RV
Using FOR XML PATH('') to concatenate the groups:
SQL Fiddle
SELECT
t.Userid,
t.Username,
Groupname = 'GROUP(' +
STUFF((
SELECT ',' + STUFF(GroupName, 1, 5, '')
FROM tbl
WHERE Userid = t.Userid
FOR XML PATH(''), TYPE).value('.', 'NVARCHAR(MAX)')
, 1, 1, '') + ')'
FROM tbl t
GROUP BY t.Userid, t.Username
DROP TABLE tbl
RESULT:
| Userid | Username | Groupname |
|--------|----------|--------------------|
| 1 | sankar | GROUP(LG,LS,NG,NS) |
| 2 | Srini | GROUP(LG,LS) |
| 3 | Aathi | GROUP(LS) |
Try the below code snippet -
select a.userid,a.username,
CASE WHEN PATINDEX('%,%',a.groupname) > 0 THEN
LEFT(a.groupname,PATINDEX('%,%',a.groupname)-3)+'('+REPLACE(a.groupname,LEFT(a.groupname,PATINDEX('%,%',a.groupname)-3),'')+')'
ELSE a.groupname
END as groupname
from
(select userid,username,
stuff((
select ',' + t.[Groupname]
from #users t
where t.Userid = t1.userid
order by t.[Groupname]
for xml path('')
),1,1,'') as groupname
from #users t1
group by userid,Username) a
Edit: Changed the code as per the requirement. Please re-check now.
Assuming userid + username combination is unique, please try following query. Also considering that you don't need parenthesis around group in case of a single group, I'v updated the below query.
explanation: I've used STUFF function to calculate the grouping of groups with a comma followed by every group code like LS,LG,
Now based on comparison of position of comma using CHARINDEX with length of string using LEN, we attach the logic either adding GROUP() or GROUP to the string
select
userid,
username,
CASE
WHEN CHARINDEX(',',groupname)<LEN(groupname)
THEN 'GROUP('+ SUBSTRING(groupname,1,LEN(groupname)-1) +')'
ELSE 'GROUP'+SUBSTRING(groupname,1,LEN(groupname)-1)
end as groupname
from
(
select
userid,
username,
stuff((
select
replace(groupname,'group','') + ','
from tbl
where
userid=t.userid and username=t.username
for xml path(''),type).value('.','varchar(max)'),1,0,'')
as groupname
from tbl t
group by userid, username
)t
and updated
sql fiddle link http://sqlfiddle.com/#!6/21f65/1
gives this exact output
Userid Username Groupname
1 Sankar GROUP(LG,LS,NG,NS)
2 Srini GROUP(LG,LS)
3 Aathi GROUPLS
Finally i have succeeded by the below query which i have developed. Thanks for you all. If you want You can copy the below query and execute in SSMS.
begin tran
Create table #temp (userid int, username varchar(50), groupname varchar(50))
insert into #temp(userid , username , groupname)
select 1, 'sankar', 'GROUPLG'
union all
select 1, 'sankar', 'GROUPLS'
union all
select 1, 'sankar', 'GROUPNG'
union all
select 1, 'sankar', 'GROUPNS'
union all
select 2, 'Srini', 'HYDRSPMLG'
union all
select 2, 'Srini', 'HYDRSPMLS'
union all
select 3, 'Ravi', 'AADSCLS'
union all
select 4, 'Arun', 'RREDFTLS'
union all
select 4, 'Arun', 'RREDFTNG'
union all
select 5, 'Raja', '1234567'
union all
select 5, 'Raja', 'ABCDESLS'
union all
select 5, 'Raja', 'ABCDESLG'
union all
select 6, 'Dhilip', 'GGGGRASCDW_RV'
union all
select 6, 'Dhilip', 'CDW_RV'
union all
select 6, 'Dhilip', 'GFNG'
union all
select 6, 'Dhilip', 'GFNS'
union all
select 7, 'Satya', '184518451845'
select * from #temp
select tp.userid , tp.username, groupname + CASE WHEN tp.flag = 1 THEN CASE WHEN ct.cnt > 1 then ' (' else '' end +
ISNULL(pt.grouptype1,'')+case when grouptype2 is not null
and grouptype1 is not null then ',' else '' end +
ISNULL(pt.grouptype2,'')+case when grouptype3 is not null
and (grouptype1 is not null
or grouptype2 is not null ) then ',' else '' end +
ISNULL(pt.grouptype3,'')+case when grouptype4 is not null
and (grouptype1 is not null
or grouptype2 is not null
or grouptype3 is not null) then ',' else '' end +
ISNULL(pt.grouptype4,'') + case when ct.cnt > 1 then ')' else '' end
ELSE ''
END as Permission
from (SELECT distinct userid , username, CASE WHEN RIGHT(groupname,2) IN ('LG','LS','NG','NS') THEN Substring(groupname,1,len(groupname)-2)
ELSE groupname END as groupname ,
CASE WHEN RIGHT(groupname,2) IN ('LG','LS','NG','NS') THEN 1
ELSE 0 END as flag from #temp ) tp
--WHERE Substring(groupname,1,len(groupname)-2) IN ('LG','LS','NG','NS')
join (select userid , [LG] as grouptype1 , [LS] as grouptype2 , [NG] as grouptype3 ,
[NS] as grouptype4
FROM (SELECT userid , RIGHT(groupname,2) as grouptype FROM #temp) as Sourcetable
PIVOT (MAX(grouptype)
for grouptype in ([LG],[LS],[NG],[NS])) As Pivottable) pt
ON tp.userid = pt.userid
join (select userid, count(*) as cnt from #temp group by userid ) ct
on ct.userid = tp.userid
DROP TABLE #temp
-- Expected Output
-- 1 Sankar GROUP(LG,LS,NG,NS)
-- 2 Srini HYDRSPM(LG,LS)
-- 3 Ravi AADSCLS
-- 4 Arun RREDFT(LS,NG)
-- 5 Raja 1234567
-- 5 Raja ABCDESLG(LG,LS)
-- 6 dhilip GGGGRASCDW_RV
rollback
This is the code I used to concatenate the first two rows which each have 6 characters each. Each row of data is set at 6.
My problem is it only returns the first concatenate needed and doesn't effect the next rows.
DECLARE #r_strands VARCHAR(MAX)
SET #r_strands=''
SELECT #r_strands= #r_strands + R_Strands
FROM rs_table
SELECT LEFT(#r_strands, +12) AS text
rs_table
r_strands
thedog
wentto
hisbed
wherei
placed
foodto
eatfor
supper
the above is an example of the single column table I want to concat every two rows
EX. result desired
r_strands
thedogwentto
hisbedwherei
placedfoodto
eatforsupper
You can use ROW_NUMBER to make pairs of two consecutive r_strands. Then use FOR XML PATH('') for concatenation:
If you have an Id to determine the order, you can replace the ORDER BY with Id instead of SELECT NULL.
SQL Fiddle
;WITH Cte AS(
SELECT *,
RN = (ROW_NUMBER() OVER(ORDER BY (SELECT NULL)) + 1) / 2
FROM rs_table
)
SELECT
r_strands = (
SELECT '' + r_strands
FROM Cte
WHERE RN = c.RN
FOR XML PATH(''), TYPE).value('.', 'NVARCHAR(MAX)'
)
FROM Cte c
GROUP BY RN
RESULT:
| r_strands |
|--------------|
| thedogwentto |
| hisbedwherei |
| placedfoodto |
| eatforsupper |
Supposing that you have an row number column (call it "id"), you can self join adjacent columns on the id, and concatenate the strings using the + string concatination operator:
select a.r_strands + b.r_strands
from rs_table a
join rs_table b
on a.id = b.id - 1
declare #t table (id int, r_strands varchar(100));
insert into #t values
(1, 'thedog'),
(2, 'wentto'),
(3, 'hisbed'),
(4, 'wherei'),
(5, 'placed'),
(6, 'foodto'),
(7, 'eatfor'),
(8, 'supper');
select r_strands + next_row
from
(
select *,
next_row = lead(r_strands) over(order by id),
is_mod = id % 2
from #t
) x
where is_mod != 0;
I have a following table:
State LAB GROUP DATE CODE ID
UP A I 1-Jan 1 345
UP R S 1-Feb 1 456
UP A S 1-Jan 2 567
DL R S 1-Feb 3 678
DL T S 1-Jan 1 789
DL A S 1-Jan 2 900
MN T S 1-Jan 3 1011
MN R I 1-Feb 1 1122
MN S I 1-Feb 2 1233
I need a pivot table of following type:
STATE A R T TOTAL
UP 2 1 0 3
DL 1 1 1 3
MN 0 1 1 2
DISTINCT COUNT OF ID FOR EACH LAB FOR EACH STATE.
I then need the pivot tables filtered for following columns:
GROUP
DATE
CODE
So 1st table will have the pivot table above counting only those records which have GROUP=S
2nd table will have the pivot table above counting only those records which have CODE=1
and so on, I wish to put multiple conditions. and generate several tables one by one and export them.
If this is possible in SQL please let me know! I ruled out excel vba due to the size of table (source table will have 800,000 records approx).
Try this :-
Select [State],[A],[R],[T],Total = [A] + [R]+ [T]
from
(
Select [State],
[A] = Sum(Case when LAB='A' then 1 else 0 END) ,
[R] = Sum(Case when LAB='R' then 1 else 0 END) ,
[T] = Sum(Case when LAB='T' then 1 else 0 END)
from YourTable
group by [State]
)a
SQL FIDDLE
CREATE TABLE #t(States VARCHAR(10),LAB VARCHAR(5),GROUPs VARCHAR(5),DATEs VARCHAR(10),CODE INT,ID INT)
INSERT INTO #t values('UP','A','I','1-Jan',1,345)
INSERT INTO #t values('UP','R','S','1-Feb',1,456)
INSERT INTO #t values('UP','A','S','1-Jan',2,567)
INSERT INTO #t values('DL','R','S','1-Feb',3,678)
INSERT INTO #t values('DL','T','S','1-Jan',1,789)
INSERT INTO #t values('DL','A','S','1-Jan',2,900)
INSERT INTO #t values('MN','T','S','1-Jan',3,1011)
INSERT INTO #t values('MN','R','I','1-Feb',1,1122)
INSERT INTO #t values('MN','S','I','1-Feb',2,1233)
SELECT States,ISNULL(A,0) A,ISNULL(R,0) R,ISNULL(T,0) T,ISNULL(A,0)+ISNULL(R,0)+ISNULL(T,0) total
FROM
(
SELECT States,LAB,Count(ID) AS cnt FROM #t GROUP BY States,LAB /*apply GROUP DATE CODE condition here*/
) AS PVT
PIVOT(MAX(cnt) FOR LAB IN (A,R,T)) pvt
Another solution using PIVOT :
WITH PivotInUse AS (
SELECT state,lab,COUNT(*) AS cnt
FROM YourTable
GROUP BY state,lab
)
SELECT STATE
,COALESCE([A], 0) AS A
,COALESCE([R], 0) AS R
,COALESCE([T], 0) AS T
,COALESCE([A], 0) + COALESCE([R], 0) + COALESCE([T], 0) AS TOTAL
FROM PivotInUse
PIVOT(SUM(cnt) FOR lab IN ([A],[R],[T])) AS p;
Your sample table
SELECT * INTO #TEMP FROM
(
SELECT 'UP' [State],'A' LAB,'I' [GROUP],'1-Jan' [DATE],1 CODE,345 ID
UNION ALL
SELECT 'UP','R','S','1-Feb',1,456
UNION ALL
SELECT 'UP','A','S','1-Jan',2,567
UNION ALL
SELECT 'DL','R','S','1-Feb',3,678
UNION ALL
SELECT 'DL','T','S','1-Jan',1,789
UNION ALL
SELECT 'DL','A','S','1-Jan',2,900
UNION ALL
SELECT 'MN','T','S','1-Jan',3,1011
UNION ALL
SELECT 'MN','R','I','1-Feb',1,1122
UNION ALL
SELECT 'MN','S','I','1-Feb',2,1233
)TAB
Now you need to get the distinct count of each state and get the sum as the result to show Total
in pivoted result.
SELECT DISTINCT [State],LAB,SUM(CNT) CNT
INTO #NEWTABLE
FROM
(
SELECT DISTINCT
[State],LAB,
CASE WHEN [State] IS NULL THEN NULL ELSE COUNT([State]) OVER(PARTITION BY [State],LAB) END CNT
FROM #TEMP
)TAB
GROUP BY [State],LAB
WITH ROLLUP
Now we need to get the distinct columns for pivot(#cols) and columns to identify and replace null with zero in pivot(#NullToZeroCols)
DECLARE #cols NVARCHAR (MAX)
DECLARE #NullToZeroCols NVARCHAR (MAX)
SET #cols = SUBSTRING((SELECT DISTINCT ',['+LAB+']' FROM #NEWTABLE GROUP BY LAB FOR XML PATH('')),2,8000)
SET #NullToZeroCols = SUBSTRING((SELECT DISTINCT ',ISNULL(['+LAB+'],0) AS ['+LAB+']'
FROM #NEWTABLE GROUP BY LAB FOR XML PATH('')),2,8000)
Join the pivotted query with the #NEWTABLE to get the Total for each State
DECLARE #query NVARCHAR(MAX)
SET #query = 'SELECT P.State,' + #NullToZeroCols + ',T2.CNT TOTAL FROM
(
SELECT DISTINCT [State],LAB,CNT FROM #NEWTABLE
) x
PIVOT
(
SUM(CNT)
FOR [LAB] IN (' + #cols + ')
) p
JOIN #NEWTABLE T2 ON P.[STATE]=T2.[STATE]
WHERE P.State IS NOT NULL AND T2.LAB IS NULL AND T2.[STATE] IS NOT NULL;'
EXEC SP_EXECUTESQL #query
Here is your result
Here is the SQLFiddle http://sqlfiddle.com/#!3/c2588/1 (If it shows any error while loading the page, just click RUNSQL, it will work)
Now if you want to get the result as you said DISTINCT COUNT OF ID FOR EACH LAB FOR EACH STATE, just change
OVER(PARTITION BY [State],LAB)
to
OVER(PARTITION BY [State],LAB,Id)
which will show the following result after executing the pivot query
This question already has answers here:
How to concatenate text from multiple rows into a single text string in SQL Server
(47 answers)
Closed 9 years ago.
I have two tables:
Employers:
emp_id: emp_name:
1 Smith
2 John
3 Terry
4 Sue
and antoher one,
Skills:
emp_id: skill:
1 10
1 12
1 14
2 5
2 15
I want to get a query which returns this:
emp_id: skill:
1 10,12,14
2 5,15
So far I'm able to get skill values as string by using:
SELECT STUFF((SELECT DISTINCT ', ' + skill) AS [text()]
FROM employers inner join skills where emp_id=1
FOR XML PATH ('')),1,1,'')
But this does not help, because I need to join the values in my project to other columns and I need also that emp_id.
Any hints?
You can use the following to concatenate the values into a single row:
select e.emp_id,
e.emp_name,
STUFF((SELECT distinct ', ' + cast(s.skill as varchar(10))
from Skills s
where e.emp_id = s.emp_id
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)')
,1,2,'') skills
from employers e;
See SQL Fiddle with Demo
Then you can still join on the employers table.
Or you can use CROSS APPLY with FOR XML PATH:
select e.emp_id,
e.emp_name,
left(s.skills, len(s.skills)-1) skills
from Employers e
cross apply
(
select cast(s.skill as varchar(10)) + ', '
from Skills s
where e.emp_id = s.emp_id
FOR XML PATH('')
) s (skills);
See SQL Fiddle with Demo
Try this one -
DECLARE #Employee TABLE
(
emp_id INT
, emp_name NVARCHAR(50)
)
DECLARE #Skill TABLE
(
emp_id INT
, skill_id INT
)
INSERT INTO #Employee (emp_id, emp_name)
VALUES
(1, 'Smith'),
(2, 'John'),
(3, 'Terry'),
(4, 'Sue')
INSERT INTO #Skill (emp_id, skill_id)
VALUES
(1, 10),
(1, 12),
(1, 14),
(2, 5),
(2, 15)
SELECT
e.emp_id
, skills =
(
SELECT STUFF((
SELECT DISTINCT ', ' + CAST(s.skill_id AS VARCHAR(10))
FROM #Skill s
WHERE s.emp_id = e.emp_id
FOR XML PATH(N''), TYPE, ROOT).value(N'root[1]', N'NVARCHAR(MAX)'), 1, 2, '')
)
FROM #Employee e