查询过去一年的活跃订阅人数和订阅人数(按天)

Posted

技术标签:

【中文标题】查询过去一年的活跃订阅人数和订阅人数(按天)【英文标题】:Query for Number of Active Subscribers and Subscriptions in Past Year (By Day) 【发布时间】:2015-06-23 15:36:39 【问题描述】:

我正在寻求编写一个查询,以使我能够捕获过去一年(按天)的活跃订阅者和订阅数。例如,下面的查询将告诉我们在 2013 年 6 月 2 日至 2014 年 6 月 1 日期间任何时候主动订阅的唯一订阅者和订阅者的数量。

SELECT      count(distinct(user_id)) as subscribers, 
            count(distinct(subscription_id)) as subscriptions
FROM        dataset
WHERE       (start_date <= to_date('01JUN2014:23:59:59','DDMONYYYY:HH24:MI:SS') and 
            end_date >= to_date('02JUN2013:00:00:00','DDMONYYYY:HH24:MI:SS')) and
            payment_amt > 0;

话虽如此,我正在寻找一个查询,该查询允许我同时捕获过去 12 个月内活跃的所有活跃订阅者和活跃订阅(过去 365 天的按天)。我正在寻找的最终数据集看起来像这样(365 行;3 列):

Ref_Date     Subscribers        Subscriptions
6/1/2014        100              150
6/2/2014        101              153
…                 …               …
5/30/2015       106              160
5/31/2015       104              155

此外,对于本文中的查询,上表中“Ref_Date”的值将是“6/1/2014”。我只想用一个数据拉取所有 365 个“Ref_Date”。 任何人都可以提供任何帮助吗?非常感谢!

【问题讨论】:

【参考方案1】:

您需要创建一个日期表并将其连接到数据中。下面的示例使用来自同一数据集的派生表来生成日期列表。

查询:

SELECT Ref_date
    ,count(DISTINCT (user_id)) AS subscribers
    ,count(DISTINCT (subscription_id)) AS subscriptions
FROM (
    SELECT DISTINCT start_date AS ref_date
    FROM dataset
    WHERE start_date BETWEEN DATEADD(YYYY,-1,CURRENT_DATE) and CURRENT_DATE
    ) dateslist
INNER JOIN dataset ON start_date < DATEADD(YYYY, 1, ref_date)
    AND end_date >= ref_date

【讨论】:

【参考方案2】:

SQL Fiddle

Oracle 11g R2 架构设置

CREATE TABLE dataset ( user_id, subscription_id, start_date, end_date, payment_amt ) AS
          SELECT  1,1, SYSDATE - 370, SYSDATE - 370 + INTERVAL '1' MONTH, 10 FROM DUAL
UNION ALL SELECT  2,1, SYSDATE - 350, SYSDATE - 350 + INTERVAL '1' MONTH, 10 FROM DUAL
UNION ALL SELECT  3,2, SYSDATE - 345, SYSDATE - 345 + INTERVAL '1' MONTH, 10 FROM DUAL
UNION ALL SELECT  4,3, SYSDATE - 310, SYSDATE - 370 + INTERVAL '1' MONTH, 10 FROM DUAL
UNION ALL SELECT  5,4, SYSDATE - 250, SYSDATE - 250 + INTERVAL '1' MONTH, 10 FROM DUAL
UNION ALL SELECT  6,5, SYSDATE - 250, SYSDATE - 250 + INTERVAL '1' MONTH, 10 FROM DUAL
UNION ALL SELECT  7,6, SYSDATE - 240, SYSDATE - 240 + INTERVAL '1' MONTH, 10 FROM DUAL
UNION ALL SELECT  8,6, SYSDATE - 230, SYSDATE - 230 + INTERVAL '1' MONTH, 10 FROM DUAL
UNION ALL SELECT  9,7, SYSDATE - 100, SYSDATE - 100 + INTERVAL '1' MONTH, 10 FROM DUAL
UNION ALL SELECT 10,8, SYSDATE -  50, SYSDATE -  50 + INTERVAL '1' MONTH, 10 FROM DUAL
UNION ALL SELECT 11,9, SYSDATE -  20, SYSDATE -  20 + INTERVAL '1' MONTH, 10 FROM DUAL
UNION ALL SELECT 12,9, SYSDATE,       SYSDATE + INTERVAL '1' MONTH,       10 FROM DUAL;

查询 1

WITH all_dates_of_year AS (
  SELECT TRUNC(SYSDATE) - INTERVAL '1' YEAR + LEVEL - 1 AS day
  FROM   DUAL
  CONNECT BY
         TRUNC(SYSDATE) - INTERVAL '1' YEAR + LEVEL - 1 <= TRUNC(SYSDATE)
)
SELECT day,
       COUNT( DISTINCT user_id ) AS num_users,
       COUNT( DISTINCT subscription_id ) AS num_subs
FROM   all_dates_of_year a
       LEFT OUTER JOIN
       dataset d
       ON ( a.day BETWEEN TRUNC( d.start_date ) AND TRUNC( d.end_date ) )
GROUP BY
       a.day

Results

|                         DAY | NUM_USERS | NUM_SUBS |
|-----------------------------|-----------|----------|
|      June, 23 2014 00:00:00 |         1 |        1 |
|      June, 24 2014 00:00:00 |         1 |        1 |
|      June, 25 2014 00:00:00 |         1 |        1 |
|      June, 26 2014 00:00:00 |         1 |        1 |
|      June, 27 2014 00:00:00 |         1 |        1 |
|      June, 28 2014 00:00:00 |         1 |        1 |
|      June, 29 2014 00:00:00 |         1 |        1 |
|      June, 30 2014 00:00:00 |         1 |        1 |
|      July, 01 2014 00:00:00 |         1 |        1 |
|      July, 02 2014 00:00:00 |         1 |        1 |
|      July, 03 2014 00:00:00 |         1 |        1 |
|      July, 04 2014 00:00:00 |         1 |        1 |
|      July, 05 2014 00:00:00 |         1 |        1 |
|      July, 06 2014 00:00:00 |         1 |        1 |
|      July, 07 2014 00:00:00 |         1 |        1 |
|      July, 08 2014 00:00:00 |         2 |        1 |
|      July, 09 2014 00:00:00 |         2 |        1 |
|      July, 10 2014 00:00:00 |         2 |        1 |
|      July, 11 2014 00:00:00 |         2 |        1 |
|      July, 12 2014 00:00:00 |         2 |        1 |
|      July, 13 2014 00:00:00 |         3 |        2 |
|      July, 14 2014 00:00:00 |         3 |        2 |
|      July, 15 2014 00:00:00 |         3 |        2 |
|      July, 16 2014 00:00:00 |         3 |        2 |
|      July, 17 2014 00:00:00 |         3 |        2 |
|      July, 18 2014 00:00:00 |         3 |        2 |
|      July, 19 2014 00:00:00 |         2 |        2 |
|      July, 20 2014 00:00:00 |         2 |        2 |
|      July, 21 2014 00:00:00 |         2 |        2 |
|      July, 22 2014 00:00:00 |         2 |        2 |
|      July, 23 2014 00:00:00 |         2 |        2 |
|      July, 24 2014 00:00:00 |         2 |        2 |
|      July, 25 2014 00:00:00 |         2 |        2 |
|      July, 26 2014 00:00:00 |         2 |        2 |
|      July, 27 2014 00:00:00 |         2 |        2 |
|      July, 28 2014 00:00:00 |         2 |        2 |
|      July, 29 2014 00:00:00 |         2 |        2 |
|      July, 30 2014 00:00:00 |         2 |        2 |
|      July, 31 2014 00:00:00 |         2 |        2 |
|    August, 01 2014 00:00:00 |         2 |        2 |
|    August, 02 2014 00:00:00 |         2 |        2 |
|    August, 03 2014 00:00:00 |         2 |        2 |
|    August, 04 2014 00:00:00 |         2 |        2 |
|    August, 05 2014 00:00:00 |         2 |        2 |
|    August, 06 2014 00:00:00 |         2 |        2 |
|    August, 07 2014 00:00:00 |         2 |        2 |
|    August, 08 2014 00:00:00 |         2 |        2 |
|    August, 09 2014 00:00:00 |         1 |        1 |
|    August, 10 2014 00:00:00 |         1 |        1 |
|    August, 11 2014 00:00:00 |         1 |        1 |
|    August, 12 2014 00:00:00 |         1 |        1 |
|    August, 13 2014 00:00:00 |         1 |        1 |
|    August, 14 2014 00:00:00 |         0 |        0 |
|    August, 15 2014 00:00:00 |         0 |        0 |
|    August, 16 2014 00:00:00 |         0 |        0 |
|    August, 17 2014 00:00:00 |         0 |        0 |
|    August, 18 2014 00:00:00 |         0 |        0 |
|    August, 19 2014 00:00:00 |         0 |        0 |
|    August, 20 2014 00:00:00 |         0 |        0 |

...

|      June, 21 2015 00:00:00 |         1 |        1 |
|      June, 22 2015 00:00:00 |         1 |        1 |
|      June, 23 2015 00:00:00 |         2 |        1 |

【讨论】:

以上是关于查询过去一年的活跃订阅人数和订阅人数(按天)的主要内容,如果未能解决你的问题,请参考以下文章

面试题 16.10. 生存人数

面试题 16.10. 生存人数

程序员面试金典-面试题 16.10. 生存人数

SQL Server:仅获取过去一年的数据

盘点2016年的移动 Web 发展

java获取过去一天,过去一月,过去一年的日期,以及截至今天过去某一段时间的时间集