If you run the below code you will get a result that looks like the following:
ITEM DIFF_QTY DATE_OUTGO WAREH COMPANY
1000 -5, -3, -4, 2017-08-01, 2017-08-02, 2017-08-03, WH CMP
Which is great, this is the output that I am looking for. Sadly this only works when a specific ITEM is selected. If I remove the WHERE then everything is put on the same row of output.
So how would I separate the results by grouping (ITEM, WAREH, COMPANY)? So that the end result would look like this:
ITEM DIFF_QTY DATE_OUTGO WAREH COMPANY
1000 -5, -3, -4, 2017-08-01, 2017-08-02, 2017-08-03, WH CMP
1001 -10, -13 2017-08-01, 2017-08-03 WH CMP
Code
DECLARE #tempTable TABLE (
ITEM nvarchar(32),
DIFF_QTY nvarchar(6),
DATE_OUTGO nvarchar(10),
WAREH nvarchar(5),
COMPANY nvarchar(5)
)
INSERT INTO #tempTable (ITEM, DIFF_QTY, DATE_OUTGO, WAREH, COMPANY)
VALUES
(1000, '-5', '2017-08-01', 'WH', 'CMP'),
(1000, '-3', '2017-08-02', 'WH', 'CMP'),
(1000, '-4', '2017-08-03', 'WH', 'CMP'),
(1001, '-10', '2017-08-01', 'WH', 'CMP'),
(1001, '-13', '2017-08-03', 'WH', 'CMP')
SELECT *
FROM #tempTable
DECLARE #itemNum nvarchar(32)
DECLARE #diffQty nvarchar(max)
DECLARE #dateOutgo nvarchar(max)
DECLARE #warehouse nvarchar(5)
DECLARE #company nvarchar(5)
SET #diffQty = ''
SET #dateOutgo = ''
SELECT
#itemNum = ITEM,
#diffQty = #diffQTY + DIFF_QTY + ', ',
#dateOutgo = #dateOutgo + DATE_OUTGO + ', ',
#warehouse = WAREH,
#company = COMPANY
FROM
#tempTable
WHERE
ITEM = 1000
SELECT #itemNum ITEM_NUM, #diffQty DIFF_QTY, #dateOutgo DATE_OUTGO, #warehouse WAREHOUSE, #company COMPANY
I've looked at multiple threads about coalesce but pretty much every solution requires that you don't do multiple things at the same time (SELECT, GROUP, COALESCE, Multiple columns etc...)
You cannot use scalar variables, like #itemNum nvarchar(32), to store tabular data.
The output you want to achieve is most commonly generated in SQL Server using FOR XML PATH:
SELECT t.ITEM,
STUFF((SELECT ',' + x.DIFF_QTY
FROM #tempTable AS x
WHERE x.ITEM = t.ITEM AND
x.WAREH = t.WAREH AND
x.COMPANY = t.COMPANY
FOR XML PATH('')), 1, 1, '') AS DIFF_QTY,
STUFF((SELECT ',' + x.DATE_OUTGO
FROM #tempTable AS x
WHERE x.ITEM = t.ITEM AND
x.WAREH = t.WAREH AND
x.COMPANY = t.COMPANY
FOR XML PATH('')), 1, 1, '') AS DATE_OUTGO
FROM #tempTable AS t
GROUP BY t.ITEM, t.WAREH, t.COMPANY
Output:
ITEM DIFF_QTY DATE_OUTGO
-----------------------------------------------------
1000 -5,-3,-4 2017-08-01,2017-08-02,2017-08-03
1001 -10,-13 2017-08-01,2017-08-03
You can use FOR XML PATH('') to concatenate the values:
SELECT
t1.ITEM,
a.DIFF_QTY,
b.DATE_OUTGO,
t1.WAREH,
t1.COMPANY
FROM #tempTable t1
CROSS APPLY(
SELECT DIFF_QTY = STUFF((
SELECT ', ' + CAST(t2.DIFF_QTY AS VARCHAR(100))
FROM #tempTable t2
WHERE
t2.ITEM = t1.ITEM
AND t2.WAREH = t1.WAREH
AND t2.COMPANY = t2.COMPANY
ORDER BY t2.DATE_OUTGO
FOR XML PATH('')
), 1, 1, '')
) a
CROSS APPLY(
SELECT DATE_OUTGO = STUFF((
SELECT ', ' + CAST(t2.DATE_OUTGO AS VARCHAR(10))
FROM #tempTable t2
WHERE
t2.ITEM = t1.ITEM
AND t2.WAREH = t1.WAREH
AND t2.COMPANY = t2.COMPANY
ORDER BY t2.DATE_OUTGO
FOR XML PATH('')
), 1, 1, '')
) b
GROUP BY
t1.ITEM, t1.WAREH, t1.COMPANY, a.DIFF_QTY, b.DATE_OUTGO
DECLARE #tempTable TABLE (
ITEM nvarchar(32),
DIFF_QTY nvarchar(6),
DATE_OUTGO nvarchar(10),
WAREH nvarchar(5),
COMPANY nvarchar(5)
)
INSERT INTO #tempTable (ITEM, DIFF_QTY, DATE_OUTGO, WAREH, COMPANY)
VALUES
(1000, '-5', '2017-08-01', 'WH', 'CMP'),
(1000, '-3', '2017-08-02', 'WH', 'CMP'),
(1000, '-4', '2017-08-03', 'WH', 'CMP'),
(1001, '-10', '2017-08-01', 'WH', 'CMP'),
(1001, '-13', '2017-08-03', 'WH', 'CMP')
SELECT *
FROM #tempTable
DECLARE #itemNum nvarchar(32)
DECLARE #diffQty nvarchar(max)
DECLARE #dateOutgo nvarchar(max)
DECLARE #warehouse nvarchar(5)
DECLARE #company nvarchar(5)
SET #diffQty = ''
SET #dateOutgo = ''
SELECT distinct ITEM ,
STUFF((SELECT ', ' + CAST(DIFF_QTY AS NVARCHAR(MAX)) [text()]
FROM #tempTable temp
where t.ITEM=temp.ITEM
FOR XML PATH(''), TYPE)
.value('.','NVARCHAR(MAX)'),1,2,'') DIFF_QTY,
STUFF((SELECT ', ' + CAST(DATE_OUTGO AS NVARCHAR(MAX)) [text()]
FROM #tempTable temp
where t.ITEM=temp.ITEM
FOR XML PATH(''), TYPE)
.value('.','NVARCHAR(MAX)'),1,2,'') DATE_OUTGO,
WAREH,COMPANY
from #tempTable t
Hope it works exactly you want
Related
with the below loop script, I am creating tables for every period. What I need is that I would like to union all these multiple tables into one single table within the same script. Can anyone help me do that?
DECLARE #Interval_List as TABLE (index_1 int, Interval VARCHAR(50), Interval_2 VARCHAR(50), From_date date, To_date date)
INSERT INTO #Interval_List VALUES (1, '2021_Q3', '2021 Q3', '2021-07-01', '2021-09-30')
INSERT INTO #Interval_List VALUES (2, '2021_Q4', '2021 Q4', '2021-10-01', '2021-12-31')
INSERT INTO #Interval_List VALUES (3, '2021_H2', '2021 H2', '2021-07-01', '2021-12-31')
INSERT INTO #Interval_List VALUES (4, '2021', '2021', '2021-07-01', '2021-12-31')
DECLARE #StartDate AS DATE
DECLARE #EndDate AS DATE
DECLARE #CurrentDate AS DATE
DECLARE #index_first int
declare #index_last int
declare #interval VARCHAR(50)
declare #interval_2 VARCHAR(50)
declare #issue_table nvarchar(max)
declare #service_table nvarchar(max)
SELECT #index_first = min(index_1), #index_last = max(index_1) FROM #Interval_List
SET #CurrentDate = #StartDate
SET #issue_table = 'dbo.table1'
SET #service_table = 'dbo.table2'
WHILE (#index_first <= #index_last)
BEGIN
SELECT #StartDate = From_date, #EndDate = To_date, #interval = Interval, #interval_2 = Interval_2 FROM #Interval_List where index_1 = #index_first
IF OBJECT_ID(#issue_table) IS NULL
BEGIN
RAISERROR('Bad object!', 11, 1);
RETURN;
END
declare #query nvarchar(max);
set #query =
N'
SELECT
A.SERVICE,
A.Service_Group,
A.Portfolio,
Interval,
SUM(Metric_1_Dividend_C_New) AS Metric_1_Dividend_C_New
'
+ N'into dbo.METRIC_1_' + #interval
+
N'
FROM
(
SELECT
ISSUE_CREATION_DATE,
ISSUE_ID,
SERVICE,
SERVICE_GROUP,
PORTFOLIO,
#Interval_2 as Interval,
AVG(Metric_No_1_Dividend) AS Metric_1_Dividend_C_New
'
+ N' from ' + #issue_table +
N' where PROJECT IS NOT NULL
AND cast(FORMAT(ISSUE_CREATION_DATE, ''yyyyMMdd'') as varchar(30)) >= cast(FORMAT(#StartDate, ''yyyyMMdd'') as varchar(30))
AND cast(FORMAT(ISSUE_CREATION_DATE, ''yyyyMMdd'') as varchar(30)) <= cast(FORMAT(#EndDate, ''yyyyMMdd'') as varchar(30))
GROUP BY ISSUE_CREATION_DATE, ISSUE_ID,SERVICE,SERVICE_GROUP,PORTFOLIO
) A
GROUP BY SERVICE,Service_Group,Portfolio,Interval
'
exec sys.sp_executesql #query,
N'#StartDate date, #EndDate date, #Interval_2 VARCHAR(50)',
#StartDate, #EndDate, #Interval_2;
SET #index_first = #index_first + 1;
END
;
Before you continue, please make sure that you read about table partitioning and creating a view for your unions, because, intuitively the problem you describe sounds like these. If neither partitioning, nor views are good for you, then read the sections below:
How can I get tables by name
SELECT [name]
FROM sys.tables
WHERE [name] LIKE '%somepattern%'
How to generate a command:
SELECT CONCAT('INSERT INTO ', [name], '(col1, col2, col3) values(', value1, ', ', value2, ', ', value3, ')')
FROM sys.tables
WHERE [name] LIKE '%somepattern%'
How to concatenate rows
You can use STRING_AGG(yourstring, 'separator'), like:
SELECT STRING_AGG(CONCAT('INSERT INTO ', [name], '(col1, col2, col3) values(', value1, ', ', value2, ', ', value3, ')'), ' UNION ')
FROM sys.tables
WHERE [name] LIKE '%somepattern%'
I have a table in SQL Server that looks something like this:
What I need is this:
I tried playing around with Pivot a little bit, but of course that won't work because Pivot isn't trying to flip multiple instances of the same field, it's aggregating over multiple instance of the same field.
Does anyone have any ideas of how I can do this in T-SQL?
You can do this easily using dynamic PIVOT. This is full working example:
IF OBJECT_ID('[dbo].[DataSource]') IS NOT NULL
BEGIN;
DROP TABLE [dbo].[DataSource];
END;
CREATE TABLE [dbo].[DataSource]
(
[ID] SMALLINT
,[Value] CHAR(1)
);
INSERT INTO [dbo].[DataSource] ([ID], [Value])
VALUES (1, 'A')
,(1, 'B')
,(1, 'C')
,(2, 'A')
,(2, 'B')
,(3, 'C')
,(4, 'A')
,(4, 'B')
,(4, 'C');
DECLARE #MaxValue INT;
WITH DataSource AS
(
SELECT ROW_NUMBER() OVER (PARTITION BY [ID] ORDER BY [Value]) AS [ValueID]
FROM [dbo].[DataSource]
)
SELECT #MaxValue = MAX([ValueID])
FROM DataSource;
DECLARE #DynamicSQLStatement NVARCHAR(MAX)
,#DynamicSQLPIVOTColumns NVARCHAR(MAX);
SELECT #DynamicSQLPIVOTColumns = STUFF
(
(
SELECT DISTINCT ',[Value' + CAST([number] AS VARCHAR(4)) + ']'
FROM master..[spt_values]
WHERE [number] BETWEEN 1 AND #MaxValue
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)')
,1
,1
,''
);
SET #DynamicSQLStatement = N'
SELECT [ID], ' + #DynamicSQLPIVOTColumns + '
FROM
(
SELECT *
,''Value'' + CAST(ROW_NUMBER() OVER (PARTITION BY [ID] ORDER BY [Value]) AS VARCHAR(12)) AS [ColumnName]
FROM [dbo].[DataSource]
) DS
PIVOT
(
MAX([value]) FOR [ColumnName] IN (' + #DynamicSQLPIVOTColumns + ')
) PVT;';
EXEC sp_executesql #DynamicSQLStatement;
and the result is:
Something wrong? The value C for the ID = 3 is in the first column, not in the last. That's because I am not aware how you are defining which value is in which column and I am using ROW_NUMBER to create such mapping. I guess in your real data you have a way of doing this.
So, let's say you have additional table like this to define this ordering:
IF OBJECT_ID('[dbo].[DataSourceOrdering]') IS NOT NULL
BEGIN;
DROP TABLE [dbo].[DataSourceOrdering];
END;
CREATE TABLE [dbo].[DataSourceOrdering]
(
[OrderID] SMALLINT
,[Value] CHAR(1)
);
INSERT INTO [dbo].[DataSourceOrdering] ([OrderID], [Value])
VALUES (1, 'A')
,(2, 'B')
,(3, 'C');
Then instead using ROW_NUMBER to defined the ordering we are going to use this table:
DECLARE #MaxValue INT;
WITH DataSource AS
(
SELECT DSO.[OrderID]
FROM [dbo].[DataSource] DS
INNER JOIN [dbo].[DataSourceOrdering] DSO
ON DS.[Value] = DSO.[Value]
)
SELECT #MaxValue = MAX([OrderID])
FROM DataSource;
DECLARE #DynamicSQLStatement NVARCHAR(MAX)
,#DynamicSQLPIVOTColumns NVARCHAR(MAX);
SELECT #DynamicSQLPIVOTColumns = STUFF
(
(
SELECT DISTINCT ',[Value' + CAST([number] AS VARCHAR(4)) + ']'
FROM master..[spt_values]
WHERE [number] BETWEEN 1 AND #MaxValue
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)')
,1
,1
,''
);
SET #DynamicSQLStatement = N'
SELECT [ID], ' + #DynamicSQLPIVOTColumns + '
FROM
(
SELECT DS.*
,''Value'' + CAST(DSO.[OrderID] AS VARCHAR(12)) AS [ColumnName]
FROM [dbo].[DataSource] DS
INNER JOIN [dbo].[DataSourceOrdering] DSO
ON DS.[Value] = DSO.[Value]
) DS
PIVOT
(
MAX([value]) FOR [ColumnName] IN (' + #DynamicSQLPIVOTColumns + ')
) PVT;';
EXEC sp_executesql #DynamicSQLStatement;
Something like this?
WITH
t AS (
SELECT 1 AS ID, 'A' AS Value
UNION ALL SELECT 1, 'B'
UNION ALL SELECT 1, 'C'
UNION ALL SELECT 2, 'A'
UNION ALL SELECT 2, 'B'
UNION ALL SELECT 3, 'C'
UNION ALL SELECT 4, 'A'
UNION ALL SELECT 4, 'B'
UNION ALL SELECT 4, 'C'
)
SELECT ID,
MAX(CASE WHEN Value = 'A' THEN Value ELSE NULL END) AS Value1,
MAX(CASE WHEN Value = 'B' THEN Value ELSE NULL END) AS Value2,
MAX(CASE WHEN Value = 'C' THEN Value ELSE NULL END) AS Value3
FROM t
GROUP BY ID
I have a table with 3 nvarchar columns, 1 time column, and 2 columns Pass and Fail. I need to display the data by time column. On each milestone, there will be the number of Pass and Fail. I use Pivot and its only output Pass result without Fail. I tried everything. Please help
This is the input data:
Col1 Col2 Col3 Time Pass Fail
------------------------------------
A B C 08:30 80 0
A B C 09:30 60 2
A B C 10:30 80 0
A B C 11:30 70 0
I'm using this code:
DECLARE #cols AS NVARCHAR(MAX),
#query AS NVARCHAR(MAX)
SELECT
#cols = STUFF((SELECT ',' + QUOTENAME(Time)
FROM Your_Table
GROUP BY Time
ORDER BY Time
FOR XML PATH(''), TYPE).value('.', 'NVARCHAR(MAX)'), 1, 1, '')
SET #query = 'SELECT Col1,Col2,Col3,' + #cols + ' from
(
SELECT Col1,Col2,Col3,Time,Pass,Fail
from TD_SanLuong_CN
) x
pivot
(
sum(Pass)
for Time in (' + #cols + ')
) p1
pivot
(
sum(Fail)
for Time in (' + #cols + ')
) p2'
execute(#query);
Can I not use pivot to Fail?
I need output result:
Col1 Col2 Col3 08:30_Pass 08:30_Fail 09:30_Pass 09:30_Fail ...
A B C 80 0 60 2
Please help. Thank you!
Hi have a look at this code, i think this what you exactly needed as you expected Output
IF OBJECT_ID('tempdb..#Temp') IS NOT NULL
Drop table #Temp
CREATE TABLE #Temp (
Col1 CHAR(1),
Col2 CHAR(1),
Col3 CHAR(1),
[Time] TIME(0),
Pass INT,
Fail INT
);
INSERT #Temp (Col1, Col2, Col3, [Time], Pass, Fail) VALUES
('A', 'B', 'C', '08:30', 80, 0),
('A', 'B', 'C', '09:30', 60, 2),
('A', 'B', 'C', '10:30', 80, 0),
('A', 'B', 'C', '11:30', 70, 0);
DECLARE #cols AS NVARCHAR(MAX),
#query AS NVARCHAR(MAX),
#cols2 AS NVARCHAR(MAX),
#cols3 AS NVARCHAR(MAX),
#Dyncols AS NVARCHAR(MAX)
SELECT
#cols = STUFF((SELECT ',' + QUOTENAME(Time)
FROM #Temp
GROUP BY [Time]
ORDER BY [Time]
FOR XML PATH(''), TYPE).value('.', 'NVARCHAR(MAX)'), 1, 1, '')
SELECT
#cols2 = STUFF((SELECT ',' + 'MAX('+QUOTENAME(Time)+')' +' As '+ '['+CAST((Time) AS VARCHAR)+'_Pass'+']'
FROM #Temp
GROUP BY [Time]
ORDER BY [Time]
FOR XML PATH(''), TYPE).value('.', 'NVARCHAR(MAX)'), 1, 1, '')
SELECT
#cols3 = STUFF((SELECT ',' + 'MAX('+QUOTENAME(Time)+')' +' As '+ '['+CAST((Time) AS VARCHAR)+'_Fail'+']'
FROM #Temp
GROUP BY [Time]
ORDER BY [Time]
FOR XML PATH(''), TYPE).value('.', 'NVARCHAR(MAX)'), 1, 1, '')
SELECT
#Dyncols = STUFF((SELECT ',' + '['+CAST((Time) AS VARCHAR)+'_Pass'+']'+','+'['+CAST((Time) AS VARCHAR)+'_Fail'+']'
FROM #Temp
GROUP BY [Time]
ORDER BY [Time]
FOR XML PATH(''), TYPE).value('.', 'NVARCHAR(MAX)'), 1, 1, '')
SET #query=';with cte
AS
(
SELECT Col1,Col2,Col3,'+#cols2+' From
(
SELECT Col1,Col2,Col3,Time,Pass,Fail
FROM #Temp
) AS X
PIVOT
(
SUM(Pass)
FOR [Time] IN ('+#cols+' )
) p1
Group by Col1,Col2,Col3
),Cte2
AS
(
SELECT '+#cols3+' From
(
SELECT Col1,Col2,Col3,Time,Pass,Fail
from #Temp
) x
PIVOT
(
SUM(Fail)
FOR Time IN ('+#cols+')
)p1
Group by Col1,Col2,Col3
)
SELECT Col1,Col2,Col3,'+#Dyncols+' FROM cte ,Cte2'
PRINT #query
EXEC(#query)
Result
Col1 Col2 Col3 08:30:00_Pass 08:30:00_Fail 09:30:00_Pass 09:30:00_Fail 10:30:00_Pass 10:30:00_Fail 11:30:00_Pass 11:30:00_Fail
A B C 80 0 60 2 80 0 70 0
I have a table tblEmpBatch
Username Filename BatchId
a f1 1
b f2 1
c f3 2
d f4 2
I want output like
Username Filename BatchId
a,b f1,f2 1
c,d f3,f4 2
How can I write sql query for this.
Try this: (To use it in your table change the table name as needed and check the column name)
CREATE TABLE #TABLE2(Username varchar(10), filename VARCHAR(10), batchid INT)
INSERT INTO #TABLE2 VALUES('a' , 'f1' , 1)
INSERT INTO #TABLE2 VALUES('b' , 'f2' , 1)
INSERT INTO #TABLE2 VALUES('c' , 'f3' , 2)
INSERT INTO #TABLE2 VALUES('d' , 'f4' , 2)
select
Username =
stuff((
select
', ' + t2.Username
from #table2 t2
where
t2.batchid = t1.batchid
group by t2.Username
for xml path(''), type).value('.', 'varchar(max)'
), 1, 2, ''),
filename =
stuff((
select
', ' + t2.filename
from #table2 t2
where
t2.batchid = t1.batchid
group by t2.filename
for xml path(''), type).value('.', 'varchar(max)'
), 1, 2, ''), batchid
from #table2 t1 group by batchid
Try this...
SELECT
GROUP_CONCAT(Username) AS Username,
GROUP_CONCAT(Filename) AS Filename,
FROM tbl
GROUP BY BatchId
declare #t table (username varchar(1),Filemname varchar(10),Batchid int)
insert into #t (username,Filemname,Batchid)values ('a','f1',1)
insert into #t (username,Filemname,Batchid)values ('b','f2',1)
insert into #t (username,Filemname,Batchid)values ('c','f3',2)
insert into #t (username,Filemname,Batchid)values ('d','f4',2)
select distinct t.[Batchid],
STUFF((SELECT distinct ', ' + t1.username
from #t t1
where t.[Batchid] = t1.[Batchid]
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)')
,1,2,'') username,
STUFF((SELECT distinct ', ' + t1.Filemname
from #t t1
where t.[Batchid] = t1.[Batchid]
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)')
,1,2,'') Filemname
from #t t;
try this it will be work fine
Select distinct ST2.BatchId as BatchID, (
Select ST1.Filename + ',' AS[text()]
From tblEmpBatch ST1
Where ST1.BatchId= ST2.BatchId
ORDER BY ST1.BatchId
For XML PATH ('')
)[FileName]
,
(
Select ST1.Username + ',' AS [text()]
From tblEmpBatch ST1
Where ST1.BatchId= ST2.BatchId
ORDER BY ST1.BatchId
For XML PATH ('')
)[UserName]
From dbo.tblEmpBatch ST2
I am having one query which returns me following output.
(No of results not same all time, means sometimes it gives 3 category,sometimes 8 category etc..)
CategoryName
Test1
Test2
Test3
Now i want that store procedure should return me these date in comma separated format.
e.g. output string should be like: Test1,Test2,Test3
Can you please tell me how can i achieve this?
this will work for all characters in your data:
set nocount on;
declare #YourTable table (BirthDay datetime, PersonName varchar(20))
insert into #YourTable VALUES ('1-10-2010', 'Joe' )
insert into #YourTable VALUES ('2-10-2010', 'Bob <&>' )
insert into #YourTable VALUES ('2-10-2010', 'Alice')
set nocount off
--Concatenation with FOR XML and eleminating control/encoded character expansion "& < >"
SELECT
p1.BirthDay
,STUFF(
(SELECT
', ' + p2.PersonName
FROM #YourTable p2
WHERE p2.BirthDay=p1.BirthDay
ORDER BY p2.PersonName
FOR XML PATH(''), TYPE
).value('.','varchar(max)')
,1,2, ''
) AS PersonNames
FROM #YourTable p1
GROUP BY p1.BirthDay
OUTPUT:
BirthDay PersonNames
----------------------- ------------------------
2010-01-10 00:00:00.000 Joe
2010-02-10 00:00:00.000 Alice, Bob <&>
(2 row(s) affected)
Try COALESCE or ISNULL:
DECLARE #returnValue varchar(MAX)
SELECT
#returnValue = COALESCE(#returnValue + ', ', '') + CategoryName
FROM
TableName
Have a look at something like (Full working example)
DECLARE #Table TABLE(
ID INT,
Val VARCHAR(50)
)
INSERT INTO #Table (ID,Val) SELECT 1, 'A'
INSERT INTO #Table (ID,Val) SELECT 1, 'B'
INSERT INTO #Table (ID,Val) SELECT 1, 'C'
INSERT INTO #Table (ID,Val) SELECT 2, 'B'
INSERT INTO #Table (ID,Val) SELECT 2, 'C'
--Concat
SELECT t.ID,
STUFF((
SELECT ',' + t1.Val
FROM #Table AS t1
WHERE t1.ID = t.ID
FOR XML PATH('')
), 1, 1, '')
FROM #Table t
GROUP BY t.ID
Also, you might find that Googling will provide a lot of answers.
One means:
SELECT STUFF((
SELECT ',' + CategoryName AS [text()]
FROM YourTable
FOR XML PATH('')
), 1, 1, '')
...but watch out for XML entities that will be escaped up - e.g. & => &
Just modify the KM answer in a store procedure
ALTER Procedure [dbo].[Payroll_rptAbsentReport]
#FromDate DateTime,
#ToDate DateTime,
#GFacatoryID UniqueIdentifier
As
Begin
-- Temporary table for Row data seperation
CREATE TABLE TestTable(GEmployeeGenInfoID uniqueidentifier, dtAttendDateTime varchar(max))
INSERT INTO
TestTable(GEmployeeGenInfoID, dtAttendDateTime)
SELECT
Payroll_tblAttendance.GEmployeeGenInfoID
,CONVERT(VARCHAR(max), dtAttendDateTime, 105)dtAttendDateTime
FROM Payroll_tblAttendance
INNER JOIN PIS.dbo.PIS_tblEmployeeGenInfo as EmployeeGenInfo ON Payroll_tblAttendance.GEmployeeGenInfoID= EmployeeGenInfo.GEmployeeGenInfoID
WHERE Payroll_tblAttendance.DayStatusID = 0 AND EmployeeGenInfo.GFactoryID=#GFacatoryID AND Payroll_tblAttendance.dtAttendDateTime Between #FromDate and #ToDate ORDER BY dtAttendDateTime
-- Final expected output
SELECT DISTINCT
EmployeeGenInfo.StrEmpName
,EmployeeGenInfo.StrEmpID
,Attendence.CardNo
,EmployeeDesignation.StrDesignationName
,EmployeeDept.StrDepartmentName
-- Count data will be in one column
,(Select COUNT(*) From TestTable Where GEmployeeGenInfoID=Attendence.GEmployeeGenInfoID) TotalAbsent
-- Row data set into one column seperate by coma
,substring( ( SELECT ', ' + dtAttendDateTime as [text()]
FROM TestTable
WHERE GEmployeeGenInfoID = Attendence.GEmployeeGenInfoID
FOR XML path(''), elements
), 3, 1000
) List
FROM
Payroll_tblAttendance as Attendence
INNER JOIN TestTable on TestTable.GEmployeeGenInfoID=Attendence.GEmployeeGenInfoID
INNER JOIN PIS.dbo.PIS_tblEmployeeGenInfo as EmployeeGenInfo ON Attendence.GEmployeeGenInfoID= EmployeeGenInfo.GEmployeeGenInfoID
INNER JOIN PIS.dbo.PIS_tblDesignationInfo as EmployeeDesignation ON EmployeeGenInfo.GDesignationInfoID= EmployeeDesignation.GDesignationInfoID
INNER JOIN PIS.dbo.PIS_tblDepartment as EmployeeDept ON EmployeeGenInfo.GDepartmentID= EmployeeDept.GDepartmentID
WHERE EmployeeGenInfo.GFactoryID=#GFacatoryID AND Attendence.DayStatusID = 0 AND Attendence.dtAttendDateTime Between #FromDate and #ToDate
DROP TABLE TestTable
END