2014-01-15 197 views
1

我有两列,我需要按日期VB.net SQL数据透视表

DateOnly    Username 
12/01/2014 00:00:00 Dave 
12/01/2014 00:00:00 Bob 
12/01/2014 00:00:00 Steve 
12/01/2014 00:00:00 Richard 
13/01/2014 00:00:00 Dave 
13/01/2014 00:00:00 Dave 
13/01/2014 00:00:00 Bob 
14/01/2014 00:00:00 Dave 

等等返回用户名的计数,总会有大约2000 - 3000条记录每天。

我要像

Username   12/01/2014   13/01/2014   14/01/2014 
Dave     1      2     1 
Bob     1      1     0 
Steve    1      0     0 
Richard    1      0     0 

显示它我希望用户选择两个日期之间进行搜索,即WHERE = 12/01/2014 and 14/01/2014

所以我不知道有多少列会有。

任何人都可以帮我解决这个问题吗?

回答

0

我的建议是首先用有限数量的日期编写查询,以便您可以获得适用于PIVOT查询的逻辑。

当你有值的数量有限,那么你可以很容易地硬编码查询:

select username, 
    [2014-01-12], [2014-01-13], [2014-01-14] 
from 
(
    select username, dateonly 
    from yourtable 
    where dateonly >= '2014-01-12' 
    and dateonly <= '2014-01-14' 
) d 
pivot 
(
    count(dateonly) 
    for dateonly in ([2014-01-12], [2014-01-13], [2014-01-14]) 
) piv; 

SQL Fiddle with Demo

一旦你有逻辑关闭,那么你可以创建一个动态SQL版本的查询。由于您将有未知的日期,因此我会创建一个日历表,其中包含将用于创建最终列值的日期。

例如,您可以创建类似表:

create table dates 
(
    dt datetime 
); 
insert into dates 
values 
('2014-01-01'), ('2014-01-02'), ('2014-01-03'), 
('2014-01-04'), ('2014-01-05'), ('2014-01-06'), 
('2014-01-07'), ('2014-01-08'), ('2014-01-09'), 
('2014-01-10'), ('2014-01-11'), ('2014-01-12'), 
('2014-01-13'), ('2014-01-14'), ('2014-01-15'); 

那么这个表将被用来创建动态列。其动态SQL版本将为:

DECLARE @cols AS NVARCHAR(MAX), 
    @query AS NVARCHAR(MAX), 
    @startdate datetime, 
    @enddate datetime 

DECLARE @ParmDefinition nvarchar(500) 
SET @ParmDefinition = N'@startdt datetime, @enddt datetime' 

-- these values would be passed into your stored procedure 
set @startdate = '2014-01-10' 
set @enddate = '2014-01-14' 

-- this creates the list of final columns to be displayed using the 
-- dates table. Using the calendar table makes sure that you return all dates you 
-- requested even if you do not have those values in DateOnly 
select @cols = STUFF((SELECT ',' + QUOTENAME(convert(varchar(10), dt, 120)) 
        from dates 
        where dt >= @startdate 
         and dt <= @enddate 
      FOR XML PATH(''), TYPE 
      ).value('.', 'NVARCHAR(MAX)') 
     ,1,1,'') 

set @query = 'SELECT username, ' + @cols + ' 
      from 
      (
       select username, dateonly 
       from yourtable 
       where dateonly >= @startdt 
       and dateonly <= @enddt 
      ) x 
      pivot 
      (
       count(dateonly) 
       for dateonly in (' + @cols + ') 
      ) p ' 

execute sp_executesql @query, 
    @ParmDefinition, 
    @startdt = @startdate, 
    @enddt = @enddate; 

请参阅SQL Fiddle with Demo。两个版本都给出了结果:

| USERNAME | 2014-01-10 | 2014-01-11 | 2014-01-12 | 2014-01-13 | 2014-01-14 | 
|----------|------------|------------|------------|------------|------------| 
|  Bob |   0 |   0 |   1 |   1 |   0 | 
|  Dave |   0 |   0 |   1 |   2 |   1 | 
| Richard |   0 |   0 |   1 |   0 |   0 | 
| Steve |   0 |   0 |   1 |   0 |   0 |