Given string:
Note: The following comma separted string is dynamic which comes with any combination.
DECLARE #Str varchar(max) = '[A-B],[B-C],[C-D],[D-E]'
Expected Result:
SUM([A-B]) AS [A-B],SUM([B-C]) AS [B-C],SUM([C-D]) AS [C-D],SUM([D-E]) AS [D-E]
My try:
SELECT 'SUM('+REPLACE(#Str,',','),SUM(')+')'
Output:
SUM([A-B]),SUM([B-C]),SUM([C-D]),SUM([D-E])
Try this
DECLARE #Str AS TABLE ([Str] varchar(max) )
INSERT INTO #Str
SELECT '[A-B],[B-C],[C-D],[D-E]'
;WITH CTE
AS
(
SELECT 'SUM( '+Split.a.value('.','nvarchar(100)')+' ) AS 'AS [Str],Split.a.value('.','nvarchar(100)') AS [Str1]
FROM
(
SELECT CAST('<S>'+(REPLACE([Str],',','</S><S>')+'</S>') AS XML ) AS [Str]
FROM #Str
)AS A
CROSS APPLY [Str].nodes('S') AS Split(a)
)
SELECT STUFF((SELECT DISTINCT ', '+ CONCAT([Str], [Str1])
FROM CTE
FOR XML PATH ('')),1,1,'') AS ExpectedResult
Result
ExpectedResult
-------------------
SUM( [A-B] ) AS [A-B], SUM( [B-C] ) AS [B-C], SUM( [C-D] ) AS [C-D], SUM( [D-E] ) AS [D-E]
Being SQL Server 2008 you would first need to create an SplitString function (it's already included in SQL Server 2016 and forward), like this one :
T-SQL split string
Then you can calculate your clauses :
select 'sum(' + Name + ', as ' + Name
from SplitString(#Str)
And finally you only need to concatenate all those rows, for example adding for xml path('')
select 'sum(' + Name + ', as ' + Name + ','
from SplitString(#Str)
for xml path('')
Simple way to achieve your task
Declare #str varchar(max) = '[A-B],[B-C],[C-D],[D-E]'
, #Main varchar(max)=''
select #Main += ',sum('+a+')'
from (select distinct value as a from STRING_SPLIT(#str , ',')) as Splt
set #Main= stuff(#Main ,1,1,'')
print #Main
Result : sum([A-B]),sum([B-C]),sum([C-D]),sum([D-E])
Related
hello friends i m trying to convert row Data with dates in column headers
this is my sql attendanceData Table
Normal Table
Original Data
and i want to convert row dates into column headers like this
Transpose
can someone tell me how i can do this in sql
i m sure using pivot i can,
so i tried sql query to pivot
SELECT Enterprise_ID, Date, Attendance
FROM attendanceData natural
join ( SELECT Enterprise_ID
FROM attendanceData
group BY Enterprise_ID
)
pivot (max(P) for Attendance in ('P' as P, 'WO' as WO)
I tried using dynamic pivot
Sample script to generate data:
create table #a
(
entrprise_id varchar(50),
datee date,
attendance varchar(10)
)
insert into #a values
('james','2018-12-22','p'),
('james','2018-12-23','p'),
('pick','2018-12-23','p'),
('rick','2018-12-23','p'),
('pick','2018-12-22','p'),
('rick','2018-12-22','p')
PIVOT Query:
DECLARE #cols AS NVARCHAR(MAX),
#query AS NVARCHAR(MAX);
SET #cols = STUFF((SELECT distinct ',' + QUOTENAME(c.datee)
FROM #a c
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)')
,1,1,'')
set #query = 'SELECT entrprise_id, ' + #cols + ' from
(
select*
from #A
) x
pivot
(
max(attendance)
for datee in (' + #cols + ')
) p '
execute(#query)
or
select *
from
(
select *
from #A
) src
pivot
(
max(attendance)
for datee in ([2018-12-22], [2018-12-23])
) piv
how to remove duplicate values from the comma seperated string in sql server. Without using functions
Declare #data varchar(max) = '34.22,768.55,34.22,123.34,12,999.0,999.0'
My expected result should be
34.22,768.55,123.34,12,999.0
i tried this query but it doesn't remove duplicates from the variable.
Declare #data varchar(max) = '34.22,768.55,34.22,123.34,12,999.0,999.0'
set #data= (select '' + cast(cast('<d>'+replace(#data, ', ',',</d><d>')+'</d>' as xml).query('distinct-values(/d)') as varchar(max)) +'')
Please try this -
DECLARE #x AS XML=''
Declare #finalstring varchar(max) = ''
DECLARE #Param AS VARCHAR(100) = '34.22,768.55,34.22,123.34,12,999.0,999.0'
SET #x = CAST('<A>'+ REPLACE(#Param,',','</A><A>')+ '</A>' AS XML)
select #finalstring = #finalstring + value + ',' from (
SELECT t.value('.', 'VARCHAR(10)') Value FROM #x.nodes('/A') AS x(t))p
GROUP BY value
PRINT SUBSTRING(#finalstring,0,LEN(#finalstring))
OUTPUT
12,123.34,34.22,768.55,999.0
For sql 2016+
Declare #data varchar(max) = '34.22,768.55,34.22,123.34,12,999.0,999.0'
Declare #finalstring varchar(max) = ''
select #finalstring = #finalstring + value + ',' from string_split(#data,',')
GROUP BY value
PRINT SUBSTRING(#finalstring,0,LEN(#finalstring))
OUTPUT
12,123.34,34.22,768.55,999.0
Try this
Declare #data varchar(max) = '34.22,768.55,34.22,123.34,12,999.0,999.0'
SELECT STUFF(
(
SELECT DISTINCT ',' + UniqNum FROM
(
SELECT CAST('<d>'+replace(#data, ',','</d><d>')+'</d>' AS XML) AS numberXml
) as t1
CROSS APPLY
(
SELECT my_Data.D.value('.','varchar(50)') as UniqNum
FROM t1.numberXml.nodes('d') as my_Data(D)
) t2
FOR XML PATH('')
), 1, 1, '')
Result
UniqNumber
---------------------------
12,123.34,34.22,768.55,999.0
Try This
Declare #data varchar(max) = '34.22,768.55,34.22,123.34,12,999.0,999.0'
;WITH CTE
AS
(
SELECT
MyStr = SUBSTRING(#data,CHARINDEX(',',#Data)+1,LEN(#data)),
Val = SUBSTRING(#data,1,CHARINDEX(',',#data)-1)
UNION ALL
SELECT
MyStr = CASE WHEN CHARINDEX(',',MyStr)>0
THEN SUBSTRING(MyStr,CHARINDEX(',',MyStr)+1,LEN(MyStr))
ELSE NULL END,
Val = CASE WHEN CHARINDEX(',',MyStr)>0
THEN SUBSTRING(MyStr,1,CHARINDEX(',',MyStr)-1)
ELSE MyStr END
FROM CTE
WHERE ISNULL(REPLACE(MyStr,',',''),'')<>''
)
SELECT
Val = SUBSTRING(List,1,LEN(List)-1)
FROM
(
SELECT
DISTINCT Val+','
FROM CTE
WHERE ISNULL(MyStr ,'')<>''
FOR XML PATH('')
)Q(List)
My Result
12,123.34,34.22,768.55,999.0
Just an another simple way of doing it.
Declare #data Nvarchar(max) = N'34.22,768.55,34.22,123.34,12,999.0,999.0'
, #data2 Nvarchar(max)='';
SELECT #data = N'SELECT #DATA_DIST= #DATA_DIST+VAL+'',''
FROM (SELECT '''+replace(#data,',',''' AS VAL UNION SELECT ''')+''')A';
EXECUTE sp_executesql #data,N'#DATA_DIST varchar(MAX) OUTPUT',#DATA_DIST=#data2 OUTPUT;
SELECT LEFT(#data2,LEN(#data2)-1);
Result:
12,123.34,34.22,768.55,999.0
I have two tables. I write a query. Date is dynamic. I can select any date. `
select a.MP,a.CP,a.Frequency,a.Time,CONVERT(varchar(12),b.date,101) as
EntryDate,b.actualtime from mpcp a, DailyData b
where a.UserID=1 and a.MpCpId=b.MpCpId and
CONVERT(varchar(12),b.EntryDate,101) between
CONVERT(varchar(12),GETDATE()-5,101) and
CONVERT(varchar(12),GETDATE()+25,101)`
Output
But i want output like
Assuming that i am storing your result in one temp table and imaging data i created one data for your requirement
try this one whether it is useful or not
create table #piv
(
mp varchar(10),
cp varchar(10),
freq varchar(10),
time int,
entryd date,
acuralize int
)
insert into #piv values
('don','asper','da',30,getdate(),0),
('dwm','donl','da',10,getdate(),3),
('qar','qpr','da',15,getdate(),5),
('qar','qpr','da',15,'01-16-17',5),
('qar','qpr','da',15,'01-15-17',5),
('qar','qpr','da',15,'01-16-17',5)
SELECT * FROM #piv
Declare #SQL varchar(max) = Stuff((Select Distinct ',' + QuoteName(entryd) From #piv Order by 1 For XML Path('')),1,1,'')
Select #SQL = '
Select *,' + #SQL + '
From #piv
Pivot (max(time) For [entryd] in (' + #SQL + ') ) p'
Exec(#SQL);
You can create a dynamic pivot. A good example is available on this link.
Good Luck !
DECLARE #cols VARCHAR(max),#sql VARCHAR(max)
SELECT #cols=ISNULL(#cols+',[','[')+ CONVERT(VARCHAR,a.EntryDate,101)+']'
FROM mpcp a, DailyData b
where a.UserID=1 and a.MpCpId=b.MpCpId and DATEDIFF(d,GETDATE(),b.EntryDate) BETWEEN -5 AND 25
GROUP BY a.time
SET #sql='
SELECT * FROM (
SELECT a.MP,a.CP,a.Frequency,a.Time,CONVERT(varchar(12),b.date,101) AS EntryDate,b.actualtime
FROM mpcp a, DailyData b
WHERE a.UserID=1 and a.MpCpId=b.MpCpId and where a.UserID=1 and a.MpCpId=b.MpCpId and DATEDIFF(d,GETDATE(),b.EntryDate) BETWEEN -5 AND 25
) AS t
PIVOT (MAX(actualtime) FOR EntryDate IN ('+#cols+') )'
EXEC(#sql)
I have the following query which is always giving the error. Could some body help me
to resolve this?
"Incorrect syntax near the keyword '#stqsql'".
My code is:
declare #strsql nvarchar(max)
set #strsql=select merchantid from employee
select *
from
(
Select s.employeeid,
COUNT(*) as TotCount
from Employee s
GROUP BY s.employeeid
)as a
pivot (avg(TotCount) for employeeid IN ('+#stqsql+')) AS NoOfRec
Unfortunately the way you are trying to get dynamic columns does not work. You will have to use something similar to the following:
DECLARE #colsPivot AS NVARCHAR(MAX),
#query AS NVARCHAR(MAX)
-- this gets the list of values that you want to pivot
select #colsPivot = STUFF((SELECT distinct ', ' + QUOTENAME(merchantid )
from employee
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)')
,1,1,'')
-- since you are use a dynamic list you have to use dynamic sql
set #query = 'SELECT ' + #colsPivot + ' from
(
SELECT s.employeeid,
COUNT(*) as TotCount
FROM Employee s
GROUP BY s.employeeid
) src
pivot
(
avg(TotCount)
for employeeid in (' + #colsPivot + ')
) p '
execute(#query)
What is the TSQL syntax to format my output so that the column values appear as a string, seperated by commas.
Example, my table CARS has the following:
CarID CarName
----------------
1 Porsche
2 Mercedes
3 Ferrari
How do I get the car names as : Porsche, Mercedes, Ferrari
SELECT LEFT(Car, LEN(Car) - 1)
FROM (
SELECT Car + ', '
FROM Cars
FOR XML PATH ('')
) c (Car)
You can do a shortcut using coalesce to concatenate a series of strings from a record in a table, for example.
declare #aa varchar (200)
set #aa = ''
select #aa =
case when #aa = ''
then CarName
else #aa + coalesce(',' + CarName, '')
end
from Cars
print #aa
If you are running on SQL Server 2017 or Azure SQL Database you do something like this :
SELECT STRING_AGG(CarName,',') as CarNames
FROM CARS
You can do this using stuff:
SELECT Stuff(
(
SELECT ', ' + CARS.CarName
FROM CARS
FOR XML PATH('')
), 1, 2, '') AS CarNames
DECLARE #CarList nvarchar(max);
SET #CarList = N'';
SELECT #CarList+=CarName+N','
FROM dbo.CARS;
SELECT LEFT(#CarList,LEN(#CarList)-1);
Thanks are due to whoever on SO showed me the use of accumulating data during a query.
Another solution within a query :
select
Id,
STUFF(
(select (', "' + od.ProductName + '"')
from OrderDetails od (nolock)
where od.Order_Id = o.Id
order by od.ProductName
FOR XML PATH('')), 1, 2, ''
) ProductNames
from Orders o (nolock)
where o.Customer_Id = 525188
order by o.Id desc
(EDIT: thanks #user007 for the STUFF declaration)
Please try this with the following code:
DECLARE #listStr VARCHAR(MAX)
SELECT #listStr = COALESCE(#listStr+',' , '') + CarName
FROM Cars
SELECT #listStr
DECLARE #SQL AS VARCHAR(8000)
SELECT #SQL = ISNULL(#SQL+',','') + ColumnName FROM TableName
SELECT #SQL