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
Related
I have a table with many columns (even number of columns). Now I need to combine the second column and third column, the forth and fifth column, sixth and seventh column....etc. How to achieve this?
I tried static one, but what about dynamic one. Assume that there are 100 or more columns.
create table tb11 ( [id] int,[A] varchar(20),[B] varchar(20),
[C] varchar(20),[D] varchar(20))
insert into tb11 values
(1,'a','b','c','d'),
(2,'e','f','g','h'),
(3,'i','j','k','l')
select * from tb11
/*
id A B C D
---- --- ---- --- ----
1 a b c d
2 e f g h
3 i j k l
*/
select id,
[A] + [B] as '1' ,
[C] + [D] as '2'
from tb11
/*output with 3 columns
id 1 2
---- ----- ------
1 ab cd
2 ef gh
3 ij kl
*/
Try this
DECLARE #SQL NVARCHAR(MAX)
SELECT #SQL = (
SELECT '
' +
STUFF((
SELECT ', ' + c.name + ' + ' + c2.name + ' AS [' + c.name + c2.name +']'
FROM sys.columns c
INNER JOIN sys.columns c2 ON c2.object_id = c.object_id
AND c2.column_id = c.column_id + 1
WHERE c.[object_id] = o.[object_id]
AND c.column_id > 1
AND c.column_id % 2 = 0
FOR XML PATH(''), TYPE).value('.', 'NVARCHAR(MAX)'), 1, 2, 'SELECT id, ') + '
FROM [' + SCHEMA_NAME(o.[schema_id]) + '].[' + o.name + ']' -- select *
FROM sys.objects o
WHERE o.[type] = 'U'
AND o.is_ms_shipped = 0
AND [name] = 'tb11'
FOR XML PATH(''), TYPE).value('.', 'NVARCHAR(MAX)')
PRINT #SQL
EXEC sys.sp_executesql #SQL
You may use schema of tables to get the list of columns and create dynamic columns name from them.
Similarly by using that schema only create you table script for new structure.
Try this:
GO
;with cte as (
select ORDINAL_POSITION as slno, COLUMN_NAME from information_schema.columns where table_name = 'tb11'
)
select * into #tab_col from cte
declare #max int
set #max = (select Count(*) -1 from #tab_col)
declare #loop int
set #loop = 0
create table newtab (
id int )
declare #columns nvarchar(max) = ''
declare #values nvarchar(max) = ''
while(#Loop <= (#Max/2))
Begin
declare #Col1 varchar(100)
declare #Col2 varchar(100)
set #Col1 = (select Column_name from #tab_col where slno = #Loop+2)
set #Col2 = (select Column_name from #tab_col where slno = #Loop+3)
declare #alter nvarchar(max)
set #alter = ' Alter table newtab add [' + cast(((#Loop/2)+1) as varchar(100)) + '] nvarchar(max) '
set #columns = #columns + ',[' + (select cast(((#Loop/2)+1) as varchar(100))) + ']'
set #values = #values + ',''' + #Col1 + #Col2 + ''''
exec sp_executesql #alter
set #loop = #loop + 2
End
set #values =( select substring( #values, 2, len(#values)))
select #values
set #columns =( select substring( #columns, 2, len(#columns)))
select #columns
declare #altertab nvarchar(max)
set #altertab = ' insert into newtab ( id, ' + #columns + ' ) values ( 1, ' + #values + ' )'
exec sp_executesql #altertab
drop table newtab
Drop table #tab_col
GO
This will not exactly give you your answer but you'll get some idea.
I have store procedure like this:
ALTER procedure [dbo].[performance] #startdate nvarchar(100),
#enddate nvarchar(100) as
begin
declare #date1 nvarchar(100)=convert(varchar, #startdate+'00:00:00.000',120)
declare #date2 nvarchar(100)= convert(varchar, #enddate+'23:59:59.000',120)
set NOCOUNT on;
select l.LocName,v.Vtype,
SUM(convert(numeric(18, 2),
DATEDIFF(MI,t.DelDate,t.Paydate))) as TotalDiff,
[dbo].[testfunctionstacknew]
(CONVERT(decimal(10,1),
AVG( CONVERT(NUMERIC(18,2),
DATEDIFF(SS,t.Paydate,t.DelDate) ) ))
) as Average
from Transaction_tbl t
left join VType_tbl v on t.vtid=v.vtid
left join Location_tbl l on t.Locid=l.Locid
where t.Locid in (select t1.Locid from Transaction_tbl t1) and
dtime between #date1 and #date2 and
Status =5
group by v.Vtype,l.LocName,l.Locid
order by l.Locid
end
I am getting out put like this:
LocName Vtype TotalDiff Average
Address Normal 15 00:10:01
Adress vip 18 00:08:01
Address VVIP 9 00:04:00
Address Pass 20 00:15:00
Goldsouk normal 45 00:18:08
Goldsouk vip 17 00:11:36
Fashion vip 78 00:35:25
Fashion VVip 2 00:01:00
but i need output in different model as
LocName Normal Vip VVip Pass Staff
Address 00:10:01 00:08:01 00:04:00 0 0
GoldSouck 00:18:08 00:11:36 0 0 0
Fashion 0 00:35:25 00:01:00 0 0
so I try to write the same stored procedure by using pivot
ALTER procedure [dbo].[ParkingSummary1]
#startdate nvarchar(100), #enddate nvarchar(100) as
begin
declare #date1 nvarchar(100) = convert(varchar, #startdate+' 00:00:00.000', 120)
declare #date2 nvarchar(100) = convert(varchar, #enddate+' 23:59:59.000', 120)
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, ' + #cols + ' from (select l.LocName,Vtype from Transaction_tbl t join VType_tbl v on t.vtid = v.vtid join dbo.Location_tbl l on t.locid=l.Locid where dtime between '''+ #date1 +''' and '''+ #date2 +'''
and Status = 5) d pivot ( count(Vtype) for Vtype in (' + #cols + ')) p '
exec sys.sp_executesql #query
end
but I while executing this am getting error like this:
Column 'Location_tbl.LocName' is invalid in the select list because it is not contained in either an aggregate function or the GROUP BY clause.
I have a stored procedure like this:
ALTER procedure [dbo].[ParkingDeatailsReportnew]
#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 Date, ' + #cols + ' from ( select v.Vtype, convert(date, dtime) as Date
from Transaction_tbl t inner join VType_tbl v on t.vtid = v.vtid where dtime between ''' + #startdate + ''' and ''' + #enddate + '''and locid = ' + (select l.Locid from Location_tbl l)
+ ' ) d pivot ( count(Vtype) for Vtype in (' + #cols + ') ) p '
execute(#query)
end
while executing this query I get following error:
expects parameter '#locid', which was not supplied.i want to take all locid from my location table
You Stored Procedure failing to run since you it is expecting get parameters #locid, #StartDate, and #EndDate
EXEC ParkingDeatailsReportnew
#logid = [yourvalue], #StartDate = '[somedate]', #enddate = 'someEndDate'
for example:
EXEC ParkingDeatailsReportnew
#logid = 1234, #StartDate = '2013/08/04 08:01:00 ', #enddate = '2013/08/04 11:21:00'
after you solve this, start solving other issues
--- edit ----
so you need to remove it from the parameters.
ALTER procedure [dbo].[ParkingDeatailsReportnew]
#startdate nvarchar(100),#enddate nvarchar(100)
Why did you have it in the first place?
I doubt that it worked at all execute requires VARCHAR, you have use sp_executesql when you use NVARCHAR
I also think that you have other errors in your logic, but you'll get there later.
Try this one -
ALTER PROCEDURE [dbo].[ParkingDeatailsReportnew]
#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 dbo.VType_tbl
FOR XML PATH(''), TYPE).value('.', 'NVARCHAR(MAX)'), 1, 1, '')
SET #query = '
SELECT Date, ' + #cols + '
from (
select 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 = ' + CAST(#locid AS VARCHAR(10)) +
' ) d pivot ( count(Vtype) for Vtype in (' + #cols + ') ) p '
EXEC sys.sp_executesql #query
END
I have a stored procedure like this:
ALTER procedure [dbo].[ParkingDeatailsReportnew]
#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 Date, ' + #cols + '
from ( select v.Vtype, convert(date, dtime) as Date
from Transaction_tbl t inner join VType_tbl v on t.vtid = v.vtid where dtime between ''' + #startdate + ''' and ''' + #enddate +
'''and locid IN ' + (select CAST(l.Locid as varchar(max)) from Location_tbl l)
+ ' ) d pivot ( count(Vtype) for Vtype in (' + #cols + ') ) p '
execute(#query)
end
While executing this am getting error like this:
Subquery returned more than 1 value. This is not permitted when the
subquery follows =, !=, <, <= , >, >= or when the subquery is used as
an expression.
How i can pass more than 1 value in my sub query?
I'd say your problem lays here:
(select CAST(l.Locid as varchar(max)) from Location_tbl l)
You're trying to form a string from an unknown amount of rows returned from that.
You could just make that part of the string.
Try this one -
ALTER PROCEDURE [dbo].[ParkingDeatailsReportnew]
#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 dbo.VType_tbl
FOR XML PATH(''), TYPE).value('.', 'NVARCHAR(MAX)'), 1, 1, '')
SET #query =
'SELECT Date, ' + #cols + '
from (
select 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
alter procedure [dbo].[ParkingDeatailsReport]
#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 Date, ' + #cols + '
from ( select v.Vtype, convert(date, dtime) as Date
from Transaction_tbl t inner join VType_tbl v
on t.vtid = v.vtid
where dtime between #startdate and #enddate
and locid = ' + CAST(#locid as varchar(max))
+ ' ) d pivot ( count(Vtype) for Vtype in (' + #cols + ') ) p '
execute(#query)
end
I am trying to execute like this:
exec ParkingDeatailsReport 5, '2013-01-01 00:00:00','2013-06-18 23:59:59'
but, I'm getting an error:Must declare the scalar variable "#startdate".
The problem is that you are building SQL in the proc, but you are not using the values in #startdate and #enddate, instead you are passing the string
You need to grab the values of these variables when you build the string - something like:
ALTER PROCEDURE [dbo].[ParkingDeatailsReport]
#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 Date, ' + #cols + '
FROM (
SELECT
v.Vtype,
convert(date, dtime) as Date
FROM Transaction_tbl t
INNER JOIN VType_tbl v
ON t.vtid = v.vtid
WHERE
dtime between ''' + #startdate + ''' and ''' + #enddate + '''
AND locid = ' + CAST(#locid as varchar(max)) + '
) d
PIVOT ( count(Vtype)
FOR Vtype in (' + #cols + ') ) p '
EXECUTE(#query)
END