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
Related
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
Actually i have three columns. ID, MedID, Name. With my query i am getting a result look like the below.
ID MedID Name
1 101 TestData1
1 124 TestData2
Query
select
cmd.ID, mm.MedID,mm.Name as Name
from
tbl1 mm
inner join
tbl2 cmd on cmd.medID= mm.MedID
where
cmd.ID= 1
Actually i am expecting a result like the below
ID MedID Name
1 101,124 TestData1,TestData2
So, how can get a result like this, Where i need to do changes in my query?
Any help appreciated. Thanks in advance !!!
Use STUFF and FOR XML PATH like this:
select id,
stuff((
select ',' + cast(MedId as varchar(30))
from t t1
where t1.id = t.id
order by MedID
for xml path('')
), 1, 1, '') MedID,
stuff((
select ',' + Name
from t t1
where t1.id = t.id
order by MedID
for xml path('')
), 1, 1, '') Name
from t
group by id;
Demo
DECLARE #TABLE TABLE (ID int, MedID varchar(10), Name varchar(10))
INSERT INTO #TABLE VALUES
(1, '101' , 'TestData1'),
(1, '124' , 'TestData2')
SELECT t.ID
, STUFF(( SELECT ', ' + MedID
FROM #TABLE
WHERE ID = t.ID
FOR XML PATH(''),TYPE)
.value('.','NVARCHAR(MAX)'),1,2,'') AS MedID
, STUFF(( SELECT ', ' + Name
FROM #TABLE
WHERE ID = t.ID
FOR XML PATH(''),TYPE)
.value('.','NVARCHAR(MAX)'),1,2,'') AS Name
FROM #TABLE t
GROUP BY t.ID
This question already has answers here:
Concatenate row values T-SQL
(15 answers)
Closed 7 years ago.
I have the following table, sorted.
ID Value Amount
1 A 10.00
2 B 4.25
3 C 2.01
4 D 5.00
How can I concatenate only consecutive pairs of rows and turn it to this:
ID Col1 Col2
1,2 A,B 10.00,4.25
3,4 C,D 2.01,5.00
And I don't want to use user-defined tables or temp tables. I am open to using
the window functions provided in SQL Server 2012 and 2014 though.
I looked at the other solutions and thought it was overkill, so I reused some and excluded or rewrote the unnecessary parts. This should result in better performance.
;WITH cte (rn, id, Value, Amount)
AS
(
SELECT ROW_NUMBER() OVER(ORDER BY id), id, Value, Amount
FROM yourtable
)
SELECT
( SELECT CAST(T.id AS VARCHAR(10)) + ','+ CAST(T1.id AS VARCHAR(10))
FROM cte AS T1
WHERE T1.rn = T.rn + 1) ID,
( SELECT CAST(T.value AS VARCHAR(10)) + ','+ CAST(T1.value AS VARCHAR(10))
FROM cte AS T1
WHERE T1.rn = T.rn + 1) COL1,
( SELECT CAST(T.Amount AS VARCHAR(10)) + ','+ CAST(T1.Amount AS VARCHAR(10))
FROM cte AS T1
WHERE T1.rn = T.rn + 1) COL2
FROM cte AS T
WHERE rn % 2 = 1
Try this,if it do not work with other sample data then let me know,
Declare #t table(ID varchar(50), Value varchar(50), Amount float)
insert into #t values(1,'A',10.00),(2,'B', 4.25),(3,'C',2.01)
,(4,'D',5.00 )
--Get the maxid
declare #MaxID int=(Select max(id) from #t)
;WITh CTE AS
(
SELECT ID,
STUFF((select ','+ id from #t where id IN(1,2) for xml path('')),1,1,'') [id1]
,STUFF((select ','+ Value from #t where id IN(1,2) for xml path('')),1,1,'') [Value]
,STUFF((select ','+ cast(Amount as varchar) from #t where id IN(1,2) for xml path('')),1,1,'') [Amount]
,1 RN
FROM #T a WHERE ID=1
UNION ALL
SELECT B.ID,
STUFF((select ','+ id from #t where id IN(RN+2,RN+3) for xml path('')),1,1,'')
,STUFF((select ','+ Value from #t where id IN(RN+2,RN+3) for xml path('')),1,1,'')
,STUFF((select ','+ cast(Amount as varchar) from #t where id IN(RN+2,RN+3) for xml path('')),1,1,'')
, RN+2
FROM cte a
CROSS APPLY(SELECT * FROM #T WHERE ID=RN+2 AND ID<=#MaxID) B
)
SELECT ID1,Value,Amount FROM CTE
This works just fine.. We just generate unique IDs for each pair using row_number and concatenate using FOR XML PATH on these IDs:
DECLARE #Test TABLE
(
ID VARCHAR(50)
, Value VARCHAR(50)
, Amount FLOAT
);
INSERT INTO #Test
(ID, Value, Amount)
VALUES
(1, 'A', 10.00)
, (2, 'B', 4.25)
, (3, 'C', 2.01)
, (4, 'D', 5.00);
;WITH cte (rn, id, Value, Amount)
AS
(
SELECT (ROW_NUMBER() OVER(ORDER BY id) + 1) / 2, id, Value, Amount
FROM #Test
)
SELECT DISTINCT
STUFF((SELECT ',' + CAST(T1.id AS VARCHAR(10))
FROM cte AS T1
WHERE T1.rn = T.rn
ORDER BY T1.id
FOR XML PATH('')), 1, 1, '') AS ID
, STUFF((SELECT ',' + CAST(T2.Value AS VARCHAR(10))
FROM cte AS T2
WHERE T2.rn = T.rn
ORDER BY T2.id
FOR XML PATH('')), 1, 1, '') AS Col1
, STUFF((SELECT ',' + CAST(T3.Amount AS VARCHAR(10))
FROM cte AS T3
WHERE T3.rn = T.rn
ORDER BY T3.id
FOR XML PATH('')), 1, 1, '') AS Col2
FROM cte AS T
Output:
ID Col1 Col2
-------------------
1,2 A,B 10,4.25
3,4 C,D 2.01,5
I have a table such as:
|Date |Name|
--------------------
|'20-May-2011'|Bob |
|'20-May-2011'|Fred|
|'20-May-2011'|Jim |
|'21-May-2011'|Bob |
|'21-May-2011'|Ed |
|'22-May-2011'|Bill|
I need a query to return:
|Date |Count|Names |
--------------------------------------
|'20-May-2011'| 3|'Bob, Fred, Jim'|
|'21-May-2011'| 2|'Bob, Ed' |
|'22-May-2011'| 1|'Bill' |
In other words, I want a list and a count of the names by date.
The best I can come up with is:
SELECT list.[Date], [Count], [Names]
FROM (
SELECT [Date],
STUFF((
SELECT ', ' + [Name]
FROM #table t2
WHERE t2.[Date] = t.[Date]
ORDER BY [Name]
FOR XML PATH('')
), 1, 2, '') AS [Names]
FROM #table t
GROUP BY [Date]
) [list]
INNER JOIN (
SELECT [Date],
COUNT(*) AS [Count]
FROM #table t
GROUP BY [Date]
) [count]
ON list.[Date] = count.[Date]
ORDER BY [Count] DESC, list.[Date]
Is there a more elegant query?
SELECT [Date],
COUNT(*) AS [Count],
STUFF((
SELECT ', ' + [Name]
FROM #table t2
WHERE t2.[Date] = t.[Date]
ORDER BY [Name]
FOR XML PATH('')
), 1, 2, '') AS [Names]
FROM #table t
GROUP BY [Date]
If you think that the Name column might contain <>'"& you should do like this instead:
SELECT [Date],
COUNT(*) AS [Count],
STUFF((
SELECT ', ' + [Name]
FROM #table t2
WHERE t2.[Date] = t.[Date]
ORDER BY [Name]
FOR XML PATH(''), TYPE
).value('.', 'varchar(max)'), 1, 2, '') AS [Names]
FROM #table t
GROUP BY [Date]
Not a whole lot better - but maybe using a single CTE to "encapsulate" the XML-PATH-stuffing into a more presentable way would work??
;WITH ConsolidatedData AS
(
SELECT
[Date],
STUFF((
SELECT ', ' + [Name]
FROM #table t2
WHERE t2.[Date] = t.[Date]
ORDER BY [Name]
FOR XML PATH('')
), 1, 2, '') AS [Names]
FROM #table t
)
SELECT
[Date], Names, COUNT(*)
FROM
ConsolidatedData
GROUP BY
[Date], Names
Not sure if you'd count this as one "compound" statement, or two.... :-)
One word of advice: try not to use SQL Server identifiers and reserved words (like Date or Order) as your own column and/or table names.... it's always rather messy....
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