数据透视表,使每个日期都为列,不包含任何聚合列

时间:2013-12-20 05:46:09

标签: sql sql-server pivot

我有以下查询,它为每位员工每天赚取一笔钱。

现在我想将这些日期行显示为列。我当前的查询及其输出如下。

declare @StartDate datetime,@EndDate datetime,@CompanyId int
set @StartDate='01/01/2013'
set @EndDate='01/31/2013'
set @CompanyId=3


;with d(date) as (
  select cast(@StartDate as datetime)
  union all
  select date+1
  from d
  where date < @EndDate
  )
select distinct d.date CDate,E.EmployeeId,Earning.EarningDescription,Earning.EarningId
,E.FirstName + ' ' + E.MiddleName + ' ' + E.LastName AS EmployeeName
from d,Employee as E
inner join Earning on E.CompanyId=Earning.CompanyId
where E.CompanyId=@CompanyId and Earning.IsOnTimeCard=1 and Earning.IsHourly=1 
order by EmployeeId,CDate,EarningId

current query output

此输出需要使用pivot进行转换。我试过看一些例子 枢纽。

根据建议的解决方案来寻找解决方案,现在我有了这个查询并且给了我错误

declare @StartDate datetime,@EndDate datetime,@CompanyId int,@cols AS NVARCHAR(MAX),@query  AS NVARCHAR(MAX)
set @StartDate='01/01/2013'
set @EndDate='01/31/2013'
set @CompanyId=3



declare @WorkingDays Table 
 (
   WDate smalldatetime
 )


;with d(date) as (
  select cast(@StartDate as datetime)
  union all
  select date+1
  from d
  where date < @EndDate
  )
  insert into @WorkingDays select  d.date from d

  SET @cols = STUFF((SELECT distinct ',' + QUOTENAME(wd.WDate) 
            FROM @WorkingDays wd
            FOR XML PATH(''), TYPE
            ).value('.', 'NVARCHAR(MAX)') 
        ,1,1,'')

  PRINT @cols

 set @query = ' 
SELECT
*
FROM
(
    select distinct WDate CDate,E.EmployeeId,Earning.EarningDescription,Earning.EarningId

    from  @WorkingDays  ,Employee as E
    inner join Earning on E.CompanyId=Earning.CompanyId
    where E.CompanyId=@CompanyId and Earning.IsOnTimeCard=1 and Earning.IsHourly=1 
) src
PIVOT
(
    MIN(src.EarningId)
    FOR src.CDate IN ('+@cols+')
) AS PivotedView '

PRINT (@query)
execute(@query)

,错误如下:

Must declare the table variable "@WorkingDays".

3 个答案:

答案 0 :(得分:1)

SQL Server PIVOT子句不支持动态列,看起来您需要动态列列表。使用PIVOT执行此操作的唯一方法是构造动态SQL语句,旋转当时所需的日期列表,然后执行此SQL。

Pivot Dynamic Columns, no Aggregation

中提供了类似的解决方案

答案 1 :(得分:0)

declare @StartDate datetime,@EndDate datetime,@CompanyId int,@cols AS NVARCHAR(MAX),@query  AS NVARCHAR(MAX)
set @StartDate='01/01/2013'
set @EndDate='01/31/2013'
set @CompanyId=3



 Create table #t
   (
     WDate smalldatetime
   )





;with d(date) as (
  select cast(@StartDate as datetime)
  union all
  select date+1
  from d
  where date < @EndDate
  )
  insert into #t select  d.date from d

  SET @cols = STUFF((SELECT distinct ',' + QUOTENAME(wd.WDate) 
            FROM #t wd
            FOR XML PATH(''), TYPE
            ).value('.', 'NVARCHAR(MAX)') 
        ,1,1,'')

  PRINT @cols

 set @query = ' 
SELECT
*
FROM
(
    select distinct WDate CDate,E.EmployeeId,Earning.EarningDescription,Earning.EarningId
    ,E.FirstName +'  + '''' + ' ''' + '+ E.MiddleName +'  + '''' + ' ''' + '+ E.LastName AS EmployeeName
    from  #t  ,Employee as E
    inner join Earning on E.CompanyId=Earning.CompanyId
    where E.CompanyId='+ CAST (@CompanyId as nvarchar(50)) +' and Earning.IsOnTimeCard=1 and Earning.IsHourly=1 
) src
PIVOT
(
    MIN(EarningDescription)
    FOR src.CDate IN ('+@cols+')
) AS PivotedView order by EmployeeId,EarningId '

PRINT (@query)
execute(@query)

drop table #t

答案 2 :(得分:-2)

  

尝试以下查询

 select '01/01/2013' Cdate, 19 EmployeeID,'regular' EarningDescription, 21 EarningID, CAST('rebecca smith' as varchar(20)) Employeename INTO #temp union all select
 '01/01/2013', 19,'OverTime', 21, 'rebecca smith'  union all select
 '01/01/2013', 19,'DoubleOvertime', 22, 'rebecca smith'  union all select
 '01/01/2013', 19,'regular', 23, 'rebecca smith'  union all select
 '01/01/2013', 19,'vacation', 104, 'rebecca smith'  union all select
 '01/01/2013', 19,'Travel', 105, 'rebecca smith'  union all select
 '02/01/2013', 19,'regular', 21, 'rebecca smith'  union all select
 '02/01/2013', 19,'OverTime', 21, 'rebecca smith'  union all select
 '02/01/2013', 19,'DoubleOvertime', 22, 'rebecca smith'  union all select
 '02/01/2013', 19,'regular', 23, 'rebecca smith'  union all select
 '02/01/2013', 19,'vacation', 104, 'rebecca smith'  union all select
 '02/01/2013', 19,'Travel', 105, 'rebecca smith'   union all select
 '03/01/2013', 19,'regular', 21, 'rebecca smith'  union all select  
 '03/01/2013', 19,'OverTime', 21, 'rebecca smith'  union all select
 '03/01/2013', 19,'DoubleOvertime', 22, 'rebecca smith'  union all select
 '03/01/2013', 18,'regular', 23, 'ganesh'  union all select
 '03/01/2013', 18,'vacation', 104, 'ganesh'  union all select
 '03/01/2013', 18,'Travel', 105, 'ganesh'  
 declare @StartDate datetime,@EndDate datetime,@CompanyId int
 set @StartDate='01/01/2013'
 set @EndDate='01/31/2013'
 set @CompanyId=3
 ;with d(date) as (
   select cast(@StartDate as datetime) as date
   union all
   select date+1
   from d
   where date < @EndDate
   )

   select * INTO #dates FROM d
   declare @dates varchar(max), @datecolumn varchar(max) 
   select @dates=COALESCE(@dates+',','')+'['+convert(varchar(MAX),date,103)+']' from #dates
   print @dates
   EXEC(
  ' SELECT * FROM (
      select distinct  convert(varchar(MAX),CDate,103) CDate,E.EmployeeId,e.EarningDescription,e.EarningId
      , EmployeeName
      from #temp e
      ) as x
      PIVOT  (
      MAX(EmployeeName)
 FOR CDate IN ('+@dates+')
 ) as pvt order by EmployeeId,EarningId')
  

如果它对您有用,请不要忘记回答。