繁体   English   中英

如何在SQL中每x个月查询一次数据?

[英]How to query data for every x month in SQL?

我有一个表格,每天用“起源”列显示链接的点击量

hitdate      originid    hitcount
==================================
2011-01-05          2          25
2011-01-05          3           3
2011-04-06          2           1          
2011-04-06          6          11
2011-05-06          7           9
2011-05-09          2          25
2011-07-10          3           3
2011-17-11          2           1          
2011-01-12          6          11
2012-01-06          7           9

我想要的是从集合的第一天(2011年5月1日)到今天为止,以编程方式对每个originID的每3个月的点击计数进行求和

我想要得到的结果

Trimester                 originid    hitcount
==============================================
2011-01-05 to 2011-31-07         1           0
                                 2          26 
                                 3           3
                                 6          11
2011-01-08 to 2011-31-10        ..          ..

我认为使用datepart(qq, ... )的其他方法可能会引起麻烦,原因是(1)这似乎无法说明跨越多个年份的日期集的可能性,并且(2)关于数据集中最早日期的假设。我试图写一个对任何开始日期都适用的解决方案,即使它不是一个月的第一天,也要复杂一些,所以也许有人可以建议一种方法简化它。

-- Sample data from the question. 
declare @hits table (hitdate date, originid bigint, hitcount int);
insert @hits values
    (convert(date, '20110501', 112), 2, 25),
    (convert(date, '20110501', 112), 3,  3),
    (convert(date, '20110604', 112), 2,  1),
    (convert(date, '20110604', 112), 6, 11),
    (convert(date, '20110605', 112), 7,  9),
    (convert(date, '20110905', 112), 2, 25),
    (convert(date, '20111007', 112), 3,  3),
    (convert(date, '20111117', 112), 2,  1),
    (convert(date, '20111201', 112), 6, 11),
    (convert(date, '20120601', 112), 7,  9);

-- Define the date range that we're concerned with.
declare @beginDate date, @endDate date;
select
    @beginDate = min(hitdate),
    @endDate = convert(date, getdate())
from 
    @hits;

-- Build a list of three-month periods that encompass the date range defined
-- above. Each period will be inclusive on the lower end of the range and
-- exclusive on the upper end.
declare @Trimester table (beginDate date, endDate date);
while @beginDate <= @endDate
begin
    insert @Trimester values (@beginDate, dateadd(m, 3, @beginDate));
    set @beginDate = dateadd(m, 3, @beginDate);
end;

-- Finally, assign each hit to one of these periods.
select
    [Trimester] = 
        convert(varchar, T.beginDate) + 
        ' to ' + 
        convert(varchar, dateadd(d, -1, T.endDate)),
    H.originid,
    hitcount = sum(H.hitcount)
from
    @hits H
    inner join @Trimester T on 
        H.hitdate >= T.beginDate and
        H.hitdate < T.endDate
group by
    T.beginDate,
    T.endDate,
    H.originid
order by
    T.beginDate,
    H.originid;

结果集为:

查询结果

我的结果集与您的结果集之间的区别是,您的结果集包含一个条目,表明originid = 1匹配为零。 由于我不知道您要将有效的originid值存储在什么地方,因此我没有做任何事情,但是只要您愿意,只要调整一下查询,就可以很容易地对其进行调整以支持该查询。加入最后一步。

更新:关于我使用datepart担忧:

  • datepart(qq, hitdate)使用datepart(qq, hitdate)会假设四分之一边界是日历季度,例如4月1日至6月30日,正如另一个答案中已经提到的那样。

  • 使用类似datepart(qq, dateadd(mm,1,hitdate))将季度移动一个月,因此您可以从示例数据中的5月1日开始获得一个季度,但假设您想从6月而不是5月开始。 您必须更改查询。

  • datepart(qq, ...本身将针对同一季度但不同年份的两个日期返回相同的值。因此,将2011年5月1日和2012年5月1日的匹配组合在一起。您可以对此进行调整,但是在撰写本文时,其他答案都没有。

  • 以上述任何一种方式使用datepart都假定季度从一个月的第一天开始。 假设结果集中最早的日期是5月15日。 我的查询会将5月15日至8月14日视为第一季度,将8月15日至11月14日视为第二季度,依此类推。

我想,如果您想要一个使用datepart(qq, ...)的解决方案,那么最后一个可能是最难克服的。 如果您对开始日期始终是一个月的第一天的假设感到满意,那么可以采用比我建议的更简单的解决方案。

在上面的查询中,如果要使用其他开始日期,则只需将想要的日期分配给@beginDate

使用Group BYDATEPART

SELECT DATEPART(qq,hitdate) AS Trimester, originid, SUM(hitcount)
FROM yourtable
GROUP BY DATEPART(qq,hitdate), originid

使用DATEPART将日期分成几个季度。 由于您的3个月不是标准季度(1月至3月,4月至6月),因此您可以使用DATEADD来抵消您的匹配日期,使其处于适当的三个月内:

Select DATEPART(qq,dateadd(mm,1,hitdate)) as QRTR, originid, SUM(hitcount)
from tablename
group by DATEPART(qq,dateadd(mm,1,hitdate)), originid

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM