将手动数据透视更改为动态数据透视表获取聚合函

时间:2013-09-17 09:42:09

标签: sql sql-server pivot

我有一个手动转动的存储过程

ALTER procedure [dbo].[performancepivot] (
    @startdate datetime, 
    @enddate datetime
) as begin

    set nocount on
    declare @date1 nvarchar(100)=convert(varchar, @startdate+'00:00:00.000',120),
            @date2 nvarchar(100)= convert(varchar, @enddate+'23:59:59.000',120);

    with cte as 
          dbo.testfunctionstacknew(convert(decimal(10,1),avg(convert(numeric(18,2), datediff(ss, t.Paydate, t.DelDate))))) as Average
        from Transaction_tbl as t
            left join VType_tbl as v on t.vtid = v.vtid
            left join Location_tbl as l on t.Locid = l.Locid
        where t.Locid in (select t1.Locid from Transaction_tbl as t1)
          and t.dtime between @date1 and @date2
          and t.Status = 5
        group by v.Vtype, l.LocName, l.Locid)

    select c.LocName, 
        max(case when c.Vtype = 'Normal' then Average end) as Normal,
        max(case when c.Vtype = 'Vip' then Average end) as Vip,
        max(case when c.Vtype = 'VVip'   then Average end) as VVip,   
        max(case when c.Vtype = 'Pass' then Average end) as Pass,
        max(case when c.Vtype = 'Staff' then Average end) as Staff  
    from cte as c group by c.LocName order by c.LocName
end

执行此操作时我得到了确切的说明..我不想手动调整..所以我尝试编写存储过程'枢轴动态'.. 我尝试写这样的存储过程:

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 + '(  
      select l.LocName,v.Vtype,[dbo].[testfunctionstacknew](
      CONVERT(decimal(10,1), AVG( CONVERT(NUMERIC(18,2),
      DATEDIFF(SS,t.Paydate,t.DelDate) ) ))) as Average  
     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 '
      print @query
     exec sp_executesql @query;
      end

但是在执行此存储过程时我收到错误:列'Location_tbl.LocName'在选择列表中无效,因为它不包含在聚合函数或GROUP BY子句中。  我的第二个存储过程有什么问题..任何人都知道请帮我找出

1 个答案:

答案 0 :(得分:0)

您需要在@query中执行命令。 “print @query”仅输出命令本身。对调试很有用,所以只需对该行进行注释..

在打印命令下插入:

exec sp_executesql @query;

更多关于sp_executesql的信息: http://technet.microsoft.com/en-us/library/ms175170(v=sql.105).aspx

编辑:

您生成的查询包含错误。此外,没有必要将日期时间转换为varchars以实现您想要的。这里应该修复两个(注意,盲编,@query只能在语法上正确)

alter procedure [dbo].[ParkingSummary1] (
     @startdate datetime
     , @enddate datetime )
     as
    begin
      DECLARE @cols AS NVARCHAR(MAX), @query  AS NVARCHAR(MAX)
      declare @params nvarchar(50) = '@date1 datetime, @date2 datetime';
      declare @date1 datetime = dateadd(day, datediff(day, 0, @startdate), 0);
      declare @date2 datetime = dateadd(day, datediff(day, 0, @enddate) + 1, 0);

      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, [dbo].[testfunctionstacknew](
            CONVERT(decimal(10,1), AVG( CONVERT(NUMERIC(18,2),
            DATEDIFF(SS,t.Paydate,t.DelDate) ) ))) as Average 
        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 >= @date1 and dtime < @date2
        and Status = 5
        group by l.LocName, VType
       ) d 
       pivot ( max(Average) for Vtype in (' + @cols + ')) p '
    print @query;
    --pass date1 and date2 as datetime parameters, not varchars.
    exec sp_executesql @query, @params, @date1, @date2
end

记得打印变量进行调试。另请检查sp_executesql网站以获取@ query,@ params,@ date1,@ date2语法的说明。