I have a stored procedure like this:
ALTER PROCEDURE [dbo].[ParkingDeatailsReportnew]
#startdate NVARCHAR(100),
#enddate NVARCHAR(100)AS BEGINDECLARE #cols AS NVARCHAR(MAX) , #query AS NVARCHAR(MAX)
SELECT #cols = STUFF(( SELECT DISTINCT ',' + QUOTENAME(Vtype)
FROM dbo.VType_tbl FOR XML PATH(''), TYPE).value('.', 'NVARCHAR(MAX)'), 1, 1, '')
SET #query =
'SELECT LocName,Date, ' + #cols + '
from (
select l.LocName,v.Vtype, convert(date, dtime) as Date
from Transaction_tbl t
join VType_tbl v on t.vtid = v.vtid
where dtime between ''' + #startdate + ''' and ''' + #enddate + '''
and locid IN (SELECT l.Locid FROM dbo.Location_tbl l)
) d pivot ( count(Vtype) for Vtype in (' + #cols + ') ) p ' EXEC sys.sp_executesql #query
END
I am getting out put like this:
Date Emaar Staff Lost Ticket Normal VIP VVIP
---------- ----------- ----------- ----------- ----------- -----------
2013-05-08 1 0 12 6 3
2013-05-09 0 0 1 0 0
I have one more table name location table.i want to show particular location name(locname) also in my output
expected output
Location Date Emaar Staff Lost Ticket Normal VIP VVIP
------- -- - ---------- ----------- ----------- ----------- ----------- -----------
Fasion 2013-05-08 1 0 12 6 3
blooimg 2013-05-09 0 0 1 0 0
If you want to see the location outputted, you need to include it in your select
'SELECT Location, Date, ' + #cols + '
from (
select Location, v.Vtype, convert(date, dtime) as Date
....
Related
I have a table which has records in the following format:
OrderID | CategoryID | Percentage
-----------------------------------------
Order1 1 50
Order1 2 100
Order1 3 70
Order2 1 85
Order2 2 75
Order2 3 100
Order3 1 50
Order3 2 60
Order3 3 80
Each order has multiple categories and each category has a percentage corresponding to that order.
I want to display it in the following format:
OrderID | Category1_% | Category2_% | Category3_%
-------------------------------------------------------
Order1 50 100 70
Order2 85 75 100
Order3 50 60 80
How do I write a query in SQL Server 2008 to retrieve percentages for each category of each (distinct) order? Please help.
Edit:
Orders table
ID | StartDate
--------------------
Order1 1/1/2016
Order2 10/1/2015
Order3 10/5/2016
The query which I executed is:
Declare #SQL varchar(max)
Declare #startDate datetime
set #startDate='1/1/2015'
Declare #endDate datetime
set #endDate= '10/1/2016'
Select #SQL = Stuff((Select Distinct ',' + QuoteName('Category'+cast(CategoryID as varchar(25))+'_%') From OrdersData Order By 1 For XML Path('')),1,1,'')
Select #SQL = 'Select [OrderID],' + #SQL +'
From (Select OrderID,Percentage,Item=''Category''+cast(CategoryID as varchar(25))+''_%'' from OrdersData join Orders on Orders.ID =OrdersData.OrderID
WHERE Orders.StartDate >= '+ ***convert(nvarchar(25), #startDate, 121)*** + ' and GCWR.StartDate <= '+ ***convert(nvarchar(25), #endDate, 121)*** +') A
Pivot (max(Percentage) For Item in (' + #SQL + ') ) p'
Exec(#SQL);
When I execute, I get an error 'Incorrect syntax near '00'.' How do I call the datetime values in the above query to display the results? Please let me know.
Just in case you need to go dynamic
Declare #SQL varchar(max)
Select #SQL = Stuff((Select Distinct ',' + QuoteName('Category'+cast(CategoryID as varchar(25))+'_%') From YourTable Order By 1 For XML Path('')),1,1,'')
Select #SQL = 'Select [OrderID],' + #SQL +'
From (Select OrderID,Percentage,Item=''Category''+cast(CategoryID as varchar(25))+''_%'' from YourTable) A
Pivot (max(Percentage) For Item in (' + #SQL + ') ) p'
Exec(#SQL);
Returns
Edit - Updated with StartDate
Declare #Date1 datetime = '2015-01-01'
Declare #Date2 datetime = '2016-10-01'
Declare #SQL varchar(max)
Select #SQL = Stuff((Select Distinct ',' + QuoteName('Category'+cast(CategoryID as varchar(25))+'_%') From YourTable Where cast(StartDate as date) between #Date1 and #Date2 Order By 1 For XML Path('')),1,1,'')
Select #SQL = 'Select [OrderID],' + #SQL +'
From (Select OrderID,Percentage,Item=''Category''+cast(CategoryID as varchar(25))+''_%'' from YourTable Where cast(StartDate as date) between '''+convert(varchar(10),#Date1,120)+''' and '''+convert(varchar(10),#Date2,120)+''') A
Pivot (max(Percentage) For Item in (' + #SQL + ') ) p'
Exec(#SQL);
Returns
Give this a try:
Select OrderID, [1] as [Category1_%], [2] as [Category2_%],[3] as [Category3_%]
From [TableName]
PIVOT (MAX([Percentage]) FOR [CategoryID] IN ([1],[2],[3])) myPivot
This assumes that you know all the possible values in the categoryID field and that each CategoryID an OrderID combination has a single percentage value.
This question already has answers here:
SQL Server dynamic PIVOT query?
(9 answers)
Closed 7 years ago.
I need to dynamically transform data in table #table from this format:
spot_id name pct
------- ---- ---
1 A 2
1 B 8
1 C 6
2 A 4
2 B 5
3 A 5
3 D 1
3 E 4
to:
spot_id A B C D E
------- --- --- --- --- ---
1 2 5 6 0 0
2 4 5 0 0 0
3 5 0 0 1 4
The thing is that I don't know in advance what the values of column "name" are or how many of them there are, so I think that I have to use some kind of dynamic SQL pivoting
Just figured out how to solve the problem:
DECLARE #cols AS NVARCHAR(MAX),
#query AS NVARCHAR(MAX)
select #cols = STUFF((SELECT ',' + QUOTENAME(name)
from (SELECT DISTINCT name FROM #table) T
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)')
,1,1,'')
set #query = N'SELECT spot_id,' + #cols + N' from
(
select spot_id, name, pct
from #table
) as x
pivot
(
max(pct)
for name in (' + #cols + N')
) as p '
exec sp_executesql #query;
If there more elegant way to do the same?
declare #t table (Spot int,name varchar(1),pct int)
insert into #t(Spot,name,pct)values(1,'A',2),(1,'B',8),(1,'C',6),(2,'A',4),(2,'B',5),(3,'A',5),(3,'D',1),(3,'E',4)
select Spot,ISNULL([A],0)[A],ISNULL([B],0)[B],ISNULL([C],0)[C],ISNULL([D],0)[D],ISNULL([E],0)[E] from (Select Spot,PCT,Name from #t)T
PIVOT(MAX(PCT) FOR Name IN ([A],[B],[C],[D],[E]))P
select Spot,ISNULL(MAX(CASE WHEN name = 'A' THEN pct END),0)A,ISNULL(MAX(CASE WHEN name = 'B' THEN pct END),0)B ,
ISNULL(MAX(CASE WHEN name = 'C' THEN pct END),0)C ,
ISNULL(MAX(CASE WHEN name = 'D' THEN pct END),0)D ,ISNULL(MAX(CASE WHEN name = 'E' THEN pct END),0)E from #t
GROUP BY Spot
Using Dynamic Query :
if object_id('tempdb..#t') is not null
drop table #t
CREATE table #t(Spot int,name varchar(1),pct int)
insert into #t(Spot,name,pct)values(1,'A',2),(1,'B',8),(1,'C',6),(2,'A',4),(2,'B',5),(3,'A',5),(3,'D',1),(3,'E',4)
DECLARE #statement NVARCHAR(max)
,#columns NVARCHAR(max)
SELECT #columns = ISNULL(#columns + ', ', '') + N'[' + tbl.name + ']'
FROM (
SELECT DISTINCT name
FROM #t
) AS tbl
SELECT #statement = ' select Spot,ISNULL([A],0)[A],ISNULL([B],0)[B],ISNULL([C],0)[C],ISNULL([D],0)[D],ISNULL([E],0)[E] from (Select Spot,PCT,Name from #t)T
PIVOT(MAX(PCT) FOR Name IN (' + #columns + ')) as pvt'
EXEC sp_executesql #statement = #statement
I have a question relating to round values from dynamic columns.
I am dynamically (Over past X days) creating a list of player with their daily score and I would like to round these scores with this kind of format ROUND(Score, 2). Here is my query:
DECLARE #Column AS NVARCHAR(MAX),
#SQL AS NVARCHAR(MAX)
SELECT [Player], [Start], [Average]
INTO #DbTemp1
FROM [PlayerScoreByWeek]
WHERE [Start] >= DateAdd(DAY, -7, GETDATE())
SELECT #Column = STUFF((SELECT ',' + QUOTENAME([Start])
FROM #DbTemp1
GROUP BY [Start]
ORDER BY [Start] FOR XML PATH(''), TYPE).value('.', 'NVARCHAR(MAX)'),1,1,'')
SET #SQL = 'SELECT [Player],' + #Column + '
INTO #DbTemp2
FROM
(
SELECT [Player], [Start], [Average]
FROM #DbTemp1
) AS SourceTable
PIVOT
(
AVG([Average])
FOR [Start] IN (' + #Column + ')
) AS PivotTable
ORDER BY Len([Player]), Player
SELECT * FROM #DbTemp2'
EXECUTE(#SQL)
The current output is as follows:
Player 2014-02-24 2014-02-25 2014-02-26 2014-02-27 2014-02-28 2014-03-01 2014-03-02
------ ---------- ---------- ---------- ---------- ---------- ---------- ----------
Carl 26.21654 55.1542 12.29612 29.16546 32.4556 21.1485 48.3652
Gene 46.13444 29.3298 16.31642 12.86592 65.6235 52.8525 31.5915
Kim 25.69554 39.5986 32.23184 34.55685 59.2125 12.2316 29.1242
And this is the desired output:
Player 2014-02-24 2014-02-25 2014-02-26 2014-02-27 2014-02-28 2014-03-01 2014-03-02
------ ---------- ---------- ---------- ---------- ---------- ---------- ----------
Carl 26.22 55.15 12.30 29.17 32.46 21.14 48.37
Gene 46.13 29.33 16.32 12.87 65.62 52.85 31.59
Kim 25.70 39.60 32.23 34.56 59.21 12.23 29.12
Given that the columns are created dynamically it is not possible to use the round function inside the '#SQL' query.
Thanks for your help !
Create another variable for your outputs - eg:
DECLARE #Column AS NVARCHAR(MAX), #Output nvarchar(max), #SQL AS NVARCHAR(MAX)
SELECT [Player], [Start], [Average] INTO #DbTemp1 FROM [PlayerScoreByWeek]
WHERE [Start] >= DateAdd(DAY, -7, GETDATE())
SELECT #Column = STUFF((SELECT ','+ QUOTENAME([Start])
FROM #DbTemp1
GROUP BY [Start]
ORDER BY [Start] FOR XML PATH(''), TYPE).value('.', 'NVARCHAR(MAX)'),1,1,''),
#Output = STUFF((SELECT ', round('+ QUOTENAME([Start])+',2) as ' + QUOTENAME([Start])
FROM #DbTemp1
GROUP BY [Start]
ORDER BY [Start] FOR XML PATH(''), TYPE).value('.', 'NVARCHAR(MAX)'),1,1,'')
SET #SQL = 'SELECT [Player],' + #Output + '
INTO #dbTemp2
FROM
(
SELECT [Player], [Start], [Average]
FROM #DbTemp1
) AS SourceTable
PIVOT
(
AVG([Average])
FOR [Start] IN (' + #Column + ')
) AS PivotTable
ORDER BY Len([Player]), Player;
select * from #DbTemp2'
EXECUTE(#SQL)
I have a stored procedure like this:
ALTER PROCEDURE [dbo].[ParkingDeatailsReportcheck]
#locid INTEGER ,
#startdate NVARCHAR(100) ,
#enddate NVARCHAR(100)
AS
BEGIN
DECLARE #cols AS NVARCHAR(MAX) ,
#query AS NVARCHAR(MAX)
SELECT #cols = STUFF((SELECT DISTINCT
',' + QUOTENAME(Vtype)
FROM VType_tbl
FOR XML PATH('') ,
TYPE
).value('.', 'NVARCHAR(MAX)'), 1, 1, '')
SET #query = 'SELECT LocName,Date, ' + #cols
+ ' from ( select l.LocName, v.Vtype, convert(date, dtime) as Date from Transaction_tbl t inner join VType_tbl v on t.vtid = v.vtid
join Location_tbl l on t.locid=l.Locid where locid='
+ CAST(#locid AS VARCHAR(MAX)) + ' and dtime between '''
+ #startdate + ''' and ''' + #enddate + ''' ) d pivot (
count(Vtype)
for Vtype in (' + #cols + ') ) p '
EXECUTE(#query)
END
while executing this stored procedure getting error like this:Ambiguous column name 'locid'.
my expected output like this:
locationname Date Emaar Staff Lost Ticket Normal VIP VVIP
---------- ----------- ----------- ----------- ----------- -----------
Fashion 2013-05-08 1 0 2 0 1
Fashion 2013-05-25 0 0 1 1 0
Fashion 2013-05-27 0 0 17 2 1
You have
join Location_tbl l on t.locid=l.Locid where locid='
change to
join Location_tbl l on t.locid=l.Locid where l.locid='
you need the table alias, it's in the dynamic SQL after the where.
Try to change:
where locid='
to:
where t.locid='
Full query:
ALTER PROCEDURE [dbo].[ParkingDeatailsReportcheck]
#locid INTEGER,
#startdate NVARCHAR(100),
#enddate NVARCHAR(100)
AS
BEGIN
DECLARE #cols AS NVARCHAR(MAX)
,#query AS NVARCHAR(MAX)
SELECT
#cols = STUFF((
SELECT DISTINCT ',' + QUOTENAME(Vtype)
FROM VType_tbl
FOR XML PATH (''), TYPE).value('.', 'NVARCHAR(MAX)'), 1, 1, '')
SET #query = '
SELECT LocName,Date, ' + #cols + '
from (
select l.LocName, v.Vtype, convert(date, dtime) as Date
from Transaction_tbl t
inner join VType_tbl v on t.vtid = v.vtid
join Location_tbl l on t.locid=l.Locid
where t.locid=' + CAST(#locid AS VARCHAR(MAX)) + '
and dtime between ''' + #startdate + ''' and ''' + #enddate + '''
) d
pivot (
count(Vtype) for Vtype in (' + #cols + ')
) p '
EXECUTE (#query)
END
I was trying on a sql query where we have search on month wise
for example my table is like
Username visited Visisted_Dated
A 1 01/11/2010
B 1 10/11/2010
A 1 03/12/2010
B 1 06/12/2010
B 1 06/12/2010
A 1 03/02/2011
B 1 05/02/2011
A 1 11/03/2011
A 1 20/03/2011
B 1 01/03/2011
Now if i want to search the users for no of visited between Feb to April i need to get output as
Users Nov_2010 Dec_2010 Jan_2011 Feb_2011 March_2011
A 1 1 0 1 2
B 1 2 0 1 1
Please let me know the way to proceed.
Thanks
I'm afraid you have to make use of dynamic SQL:
DECLARE #Sql VARCHAR(8000)
DECLARE #ColumnNames VARCHAR(1000)
DECLARE #BeginDate DATETIME
DECLARE #EndDate DATETIME
SET #BeginDate = '2010-11-1'
SET #EndDate = '2011-4-1'
SET #ColumnNames = ''
WHILE #BeginDate <= #EndDate
BEGIN
SET #ColumnNames = #ColumnNames + ',[' + DateName(month,#BeginDate) + '_' + Cast(Year(#BeginDate) AS VARCHAR(4)) + ']'
SET #BeginDate = DateAdd(Month, 1, #BeginDate)
END
IF Len(#ColumnNames) > 0
SET #ColumnNames = Right(#ColumnNames, Len(#ColumnNames) - 1)
PRINT #ColumnNames
SET #Sql = '
WITH U AS
(
SELECT UserName, DateName(month,Visited_Dated) + ''_'' + Cast(Year(Visited_Dated) AS VARCHAR(4)) AS VisitedMonth, Visited
FROM Users
)
SELECT *
FROM U
PIVOT (
SUM(Visited) FOR VisitedMonth IN (' + #ColumnNames + ')
) AS P'
EXEC (#Sql)
There it´s a solution based on PIVOT
SELECT UserName,[201011], [201012], [201101], [201102], [201103]
FROM
(SELECT UserName,Visited,convert(varchar(6),[Visited_Dated],112) Periodo
FROM [Table]) AS st
PIVOT
(
COUNT(Visited)
FOR Periodo IN ([201011], [201012], [201101], [201102], [201103])
) AS pt;