【问题标题】:Count users who have repeatedly called no sooner than 6 days post first call统计在首次通话后 6 天内多次拨打电话的用户
【发布时间】:2017-07-30 06:29:17
【问题描述】:

我必须计算用户在接下来的 7 天内(天数必须灵活)或更多的重复次调用。 查询应该只考虑比表中最后一个日期早 7 天的记录。

我的数据看起来像这样:

call_date   user  
2017-05-01  100   
2017-05-01  500   
2017-05-02  200   
2017-05-02  300   
2017-05-03  300   
2017-05-04  100   
2017-05-05  400   
2017-05-06  500   
2017-05-07  600   
2017-05-08  200   
2017-05-09  700   
2017-05-10  500   
2017-05-11  400   
2017-05-12  300   
2017-05-13  100   
2017-05-14  200   

查询的期望输出是:

call_date   user count
2017-05-01  100  2  
2017-05-01  500  2  
2017-05-02  200  2  
2017-05-02  300  2  
2017-05-03  300  1  
2017-05-04  100  1  
2017-05-05  400  2 
2017-05-06  500  2 
2017-05-07  600  1 

解释:

  • 在列出应考虑第一个联系人的日期时(user 100 调用 2017-05-012017-05-042017-05-13)但仅显示 2017-05-01
  • 对于user 100,只应考虑7 天内 的记录,因此user 100 的count 变为22017-05-012017-05-04 ; 排除 2017-05-13 因为超出范围)为call_date 2017-05-01
  • 2017-05-07 之后的记录不被考虑,因为它是比最大日期早 7 天的日期,即2017-05-14

此查询必须在 25+ 百万条记录上运行,因此优化的查询将增加优势。

我不太确定如何解决这个问题;非常感谢您对查询的详细解释。

【问题讨论】:

  • 非常感谢您对所需输出的详细说明。除了使用rand(),至少对我来说,你的计数毫无意义。
  • 进一步解释@Solarflare 请求:用户 100 和 call_date 5/1/2017 的 2 计数从何而来?用户 500 和 call_date 5/1/2016 的 0 计数从何而来? ...等等。
  • 检查是否有任何 these 与您要查找的内容接近。
  • @Solarflare 我已经添加了解释。
  • @joanolo。您能否将您的查询添加为答案,以便我接受。谢谢。

标签: mysql sql date count


【解决方案1】:

假设这是您的表定义(我已将 user 更改为 user_id 以避免与保留关键字冲突):

CREATE TABLE calls
(
    call_date date NOT NULL, 
    user_id integer NOT NULL
    /* no primary key. There *can* be duplicate rows, that could be
       changed if call_date were instead call_datetime. Then:
       PRIMARY KEY (user_id, call_datetime)
       Assumed user's cannot make simultaneous calls, nor any faster than
       the datetime resolution.
    */ 
)
;
-- These indexes will help `using index` query plans.
CREATE INDEX idx_calls_user_id_call_date ON calls(user_id, call_date) ;
CREATE INDEX idx_calls_call_date_user_id ON calls(call_date, user_id) ;

...我们会导入您的数据。然后我们可以查询数据库:

SELECT
    call_date, user_id, 
    -- Count of the number of calls on `call_date` for `user_id`
    count(call_date) AS count_on_date,
    -- Count of the number of calls between `call_date` and the next 6 days (including both)
    (SELECT count(call_date) FROM calls c1 WHERE c1.user_id = c.user_id AND c1.call_date BETWEEN c.call_date AND c.call_date + interval 6 day) AS count_next_7_days
FROM
    calls c
    -- The next JOIN is used to retrieve the `reference date`, and do it only once.
    -- This will allow to take into account only dates from (2017-05-14 - 13 day) = 2017-05-01 and (2017-05-14 - 7 day) = 2017-05-07
    JOIN (SELECT max(call_date) AS ref_date FROM calls) AS d ON c.call_date BETWEEN ref_date - interval 13 day AND ref_date - interval 7 day
GROUP BY
    call_date, user_id
ORDER BY
    call_date, user_id ;

此查询将返回:

通话日期 |用户 ID | count_on_date | count_next_7_days :--------- | ------: | ------------: | ----------------: 2017-05-01 | 100 | 1 | 2 2017-05-01 | 500 | 1 | 2 2017-05-02 | 200 | 1 | 2 2017-05-02 | 300 | 1 | 2 2017-05-03 | 300 | 1 | 1 2017-05-04 | 100 | 1 | 1 2017-05-05 | 400 | 1 | 2 2017-05-06 | 500 | 1 | 2 2017-05-07 | 600 | 1 | 1

dbfiddle here

【讨论】:

    【解决方案2】:

    你试过DAYOFWEEK()函数吗? This link 应该会有所帮助。

    【讨论】:

    • 我花了 7 天来描述问题,可以是任意天数。
    • 这本质上是一个仅链接的答案,因此将来可能会被审查并删除。如果您认为该问题与另一个问题重复,那么在该问题下发表评论会更好。由于在获得 50 次代表之前您无法做到这一点,因此最好推迟到可以做到的时候。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-12-21
    相关资源
    最近更新 更多