2

以下代码可能是不言自明的

列出 6 月 1 日的活跃订阅者数量

select 
    count(subscribers) as activeSubscribers 
from subscriberlist sub 
where 
    to_date('2012-06', 'yyyy-mm') 
        between sub.firstDayOfSubscription and sub.lastDayOfSubscription

但是,如果我想在过去一年的每个月初获得订阅者的数量,我该怎么办(除了更改查询中的日期并重复)。

4

2 回答 2

1

您可以按如下方式生成月份列表:

SELECT add_months (trunc (to_date('01/01/2012','MM/DD/YYYY'), 'MM'), 1*LEVEL -1) FirstDay
        FROM Dual
     CONNECT BY LEVEL <= MONTHS_BETWEEN(to_date('12/31/2012','MM/DD/YYYY'), to_date('01/01/2012','MM/DD/YYYY')) + 1
       ORDER BY FirstDay

这将为您提供以下输出:

FIRSTDAY
--------
January, 01 2012 00:00:00+0000
February, 01 2012 00:00:00+0000
March, 01 2012 00:00:00+0000
April, 01 2012 00:00:00+0000
May, 01 2012 00:00:00+0000
June, 01 2012 00:00:00+0000
July, 01 2012 00:00:00+0000
August, 01 2012 00:00:00+0000
September, 01 2012 00:00:00+0000
October, 01 2012 00:00:00+0000
November, 01 2012 00:00:00+0000
December, 01 2012 00:00:00+0000

然后,您可以将该查询包含为内联视图,如下所示:

SELECT months.FirstDay,
       (SELECT count(subscribers)
          FROM subscriberlist sub
         WHERE months.FirstDay BETWEEN sub.firstDayOfSubscription AND sub.lastDayOfSubscription
       ) AS activeSubscribers
FROM (SELECT add_months(trunc (to_date('01/01/2012','MM/DD/YYYY'), 'MM'), 1*LEVEL -1) FirstDay
        FROM Dual
     CONNECT BY LEVEL <= MONTHS_BETWEEN(to_date('12/31/2012','MM/DD/YYYY'), to_date('01/01/2012','MM/DD/YYYY')) + 1
       ORDER BY FirstDay) Months

我可能会将它包装在一个接受 @startDate 和 @endDate 参数的存储过程中,以定义您感兴趣的日期范围,但我遵循您的语法,日期范围是用字符串定义的。

我正在使用这个SqlFiddle玩这个

于 2012-10-23T18:06:30.590 回答
0

这对于日期查找表来说可能是一个很好的用途。我发现它们足够有用,可以尝试在任何体面的数据库中始终拥有一个。

在您的数据库中建立一个表,每天一行,持续一段合理的时间......比如说从十年前到十年后(取决于您运行的查询类型)。

在表中添加一些基于日期的字段:

日期周周_结束月月_DayOf月_开始年营业_日周末假期等...

这样做的方便之处在于,一旦它被填充,您可以通过日期字段将其连接到其他表,以便根据需要按日期汇总或过滤数据。例如:

select 
    dt.Month
    count(subscribers) as activeSubscribers 
from subscriberlist sub 
    join (select unique datelookup.Month_Beginning
          from date_reference ) dt
    on dt.Month_Beginning between sub.firstDayOfSubscription and sub.lastDayOfSubscription
group by 
    dt.Month;

(在我脑海中,我不确定这种语法是否完全正确,尤其是对于 Oracle。)

如果您无法在数据库中添加一个,您可以创建一个临时表作为查询的一部分,并用您关心的日期范围填充它。

于 2012-10-23T18:24:42.143 回答