2009-05-06 68 views
3

我有用戶登錄數據與時間戳,我想要做的是得到一年的登錄直方圖,但隨着年份開始在任意日期。例如,我需要以下信息:SQL Server非標準的基於日期的直方圖

1 May 2005 - 30 Apr 2006 | 525 
1 May 2006 - 30 Apr 2007 | 673 
1 May 2007 - 30 Apr 2008 | 892 
1 May 2006 - 30 Apr 2009 | 1047 

第一列中的標籤並不重要,但日期範圍是。我知道我可以用海峽歲月將其分解:

SELECT YEAR([date]) AS [year], COUNT(*) AS cnt 
FROM logins 
GROUP BY YEAR([date]) 
ORDER BY [year] 

但是,這並沒有給我我想要的數據範圍。如何才能做到這一點?

回答

3
declare @baseDate datetime 
set @baseDate = '1 May 2005' 

SELECT 
    datediff(year, @baseDate, [date]) AS YearBucket 
    ,COUNT(*) AS cnt 
FROM logins 
GROUP BY datediff(year, @baseDate, [date]) 
ORDER BY datediff(year, @baseDate, [date]) 

編輯 - 抱歉,你是正確的。這裏有一個固定的版本(我應該使用的測試表...開始),如果你想比天更精細

create table logins (date datetime, foo int) 
insert logins values ('1 may 2005', 1) 
insert logins values ('1 apr 2006', 2) 
insert logins values ('1 may 2006', 3) 

declare @baseDate datetime 
set @baseDate = '1 May 2005' 

SELECT 
    datediff(day, @baseDate, [date])/365 AS YearBucket 
    ,COUNT(*) AS cnt 
FROM logins 
GROUP BY datediff(day, @baseDate, [date])/365 
ORDER BY datediff(day, @baseDate, [date])/365 

更改DATEDIFF單位。

編輯#2 - 好吧,這裏是一個更強大的解決方案,處理閏年:) 編輯#3 - 實際上這不處理閏年,而是允許指定可變的時間間隔。使用dateadd(year,1,@baseDate)進行閏年安全方法。

declare @baseDate datetime, @interval datetime 
[email protected] is expressed as time above 0 time (1/1/1900) 
select @baseDate = '1 May 2005', @interval = '1901' 

declare @timeRanges table (beginIntervalInclusive datetime, endIntervalExclusive datetime) 
declare @i int 
set @i = 1 
while @i <= 10 
begin 
    insert @timeRanges values(@baseDate, @baseDate + @interval) 
    set @baseDate = @baseDate + @interval 
    set @i = @i + 1 
end 

SELECT 
    tr.beginIntervalInclusive, 
    tr.endIntervalExclusive, 
    COUNT(*) AS cnt 
FROM logins join @timeRanges as tr 
    on logins.date >= tr.beginIntervalInclusive 
     and logins.date < tr.endIntervalExclusive 
GROUP BY tr.beginIntervalInclusive, tr.endIntervalExclusive 
ORDER BY tr.beginIntervalInclusive 
+0

給出完全相同的結果,只是沒有前一年。 – cdeszaq 2009-05-06 17:50:59

1

如果你可以找到一種方法來定義你的日期範圍在一個單獨的表中,然後選擇一個標籤和兩列日期,並加入你的主要查詢這樣的東西這取決於你的表。

Select Count(*) as NoLogons, DateRangeLabel 
From logins a 
inner join 
(
Select 
DateRangeLabel, StartDate, EndDate 
From tblMyDates 
) b 
on a.date between b.startdate and b.enddate 
Group by DateRangeLabel