简体   繁体   English

选择总和达到700的记录

[英]Select record where SUM reaches 700

I have a score table where every record comes with a variable number of points, a timestamp and a mobile user ID. 我有一个分数表,其中的每条记录都带有可变数量的分数,时间戳和移动用户ID。

这是桌子的样子

I have the task of figuring out the average time it takes a user to obtain 700 points. 我的任务是弄清楚用户获得700点的平均时间。

How can I use SQL find out the record id where the SUM of total_points reaches 700 in order to compare timestamps and do this for every user. 我如何使用SQL找出total_points的SUM达到700的记录ID,以便比较时间戳并针对每个用户执行此操作。

Is a python script the best approach to solve this problem? python脚本是解决此问题的最佳方法吗? Say I get the 2 timestamps (first ever and the one where total_points reached 700) for users in my database who made >= 700 points in order to come up with an average time for all my users. 假设我为数据库中的用户获得了2个时间戳(有史以来第一个时间戳,total_points达到700个时间戳),这些用户的得分> = 700,以便得出我所有用户的平均时间。

Or is this possible to do without having to write a script? 还是无需编写脚本就可以做到这一点?

Any help or guidance is appreciated. 任何帮助或指导表示赞赏。

Here you go. 干得好。 If the data is: 如果数据是:

create table score (
  id int,
  mobile_user_id int,
  report_date datetime,
  total_points int
);

insert into score (id, mobile_user_id, report_date, total_points)
  values
  (1, 123, '2018-07-23', 100),
  (1, 123, '2018-07-24', 200),
  (1, 123, '2018-07-25', 500),
  (1, 123, '2018-07-26', 200),
  (2, 124, '2018-06-03', 800),
  (3, 125, '2018-06-17', 150);

The query is: 查询是:

with a as (
  select
      id, mobile_user_id, report_date,
      sum(total_points) over(partition by id order by report_date)
        as points_so_far
    from score
), 
b as (
  select id, min(report_date) as obtain_date
    from a where points_so_far >= 700
    group by id
)
select s.id, s.initial_date, b.obtain_date
  from b join (
    select id, min(report_date) as initial_date 
      from score group by id  
  ) s on s.id = b.id;

Result: 结果:

id           initial_date         obtain_date          
-----------  -------------------  ---------------------
1            2018-07-22 20:00:00  2018-07-24 20:00:00  
2            2018-06-02 20:00:00  2018-06-02 20:00:00  

This will list all users with a total score equal to or over 700 points. 这将列出所有总得分等于或超过700分的用户。 It also list the start date and end date for the user, and the total number of days in that period. 它还列出了用户的开始日期和结束日期,以及该时间段的总天数。

SELECT
    `mobile_user_id`,
    MIN(`report_date`) as `points_start`,
    MAX(`report_date`) as `points_end`,
    DATEDIFF(MIN(`report_date`),MIN(`report_date`)) as `duration_days`
    count(`total_points`) as `total`
FROM `points_table`
GROUP BY `mobile_user_id`
HAVING `total` >= 700

I assume your on version 5.7 or below, that is window functions are out of the window (pun, ha, ha). 我假设您的版本是5.7或更低,即窗口函数不在窗口范围内(pun,ha,ha)。 So you'd need to calculate the rolling sum using a subquery, that sums all points from earlier reports. 因此,您需要使用子查询来计算滚动总和,该子查询求和来自较早报告的所有点。

Use that to filter for only reports at or after the sum of points reached 700. 使用该过滤器仅过滤点总数达到700或之后的报告。

Group that result by user and get the minimum time stamp for each user, when they reached the 700 points or topped them. 当用户达到或超过700分时,按用户对结果进行分组并获得每个用户的最小时间戳。

Inner join the overall minimum time stamp per user, which you again get by grouping. 内部加入每个用户的整体最小时间戳,您可以通过分组再次获得。 The inner join will also eliminate rows from the second grouping subquery, that are from users with less than 700 points. 内部联接还将消除第二个分组子查询中来自少于700点的用户的行。

Get the difference of the two time stamps and calculate the average of that difference. 获取两个时间戳的差,然后计算该差的平均值。

SELECT avg(timestampdiff(SECOND, x2.report_date, x1.report_date)) duration
       FROM (SELECT t1.mobile_user_id,
                    min(t1.report_date) report_date
                    FROM elbat t1
                    WHERE (SELECT sum(t2.total_points)
                                  FROM elbat t2
                                  WHERE t2.mobile_user_id = t1.mobile_user_id
                                        AND (t2.report_date < t1.report_date
                                              OR t2.report_date = t1.report_date
                                                 AND t2.id < t1.id)) >= 700
                    GROUP BY t1.mobile_user_id) x1
            INNER JOIN (SELECT t1.mobile_user_id,
                               min(t1.report_date) report_date
                               FROM elbat t1
                               GROUP BY t1.mobile_user_id) x2
                                        ON x2.mobile_user_id = x1.mobile_user_id;

What you need is a table with this sort of schema - 您需要的是具有这种模式的表-

user_id, time_when_700_points_achieved (timestamp) , user_start_time (timestamp)

Here is the query for it - 这是它的查询-

select user_id, max(report_date) as time_when_700_points_achieved , min(report_date) as user_start_time  
from tablename
where points <= 700
group by user

After you achieve this, you can easily take the minute difference between two timestamps. 完成此操作后,您可以轻松获取两个时间戳之间的minute差。

Assumption - There will be a hit when a user reaches 700 假设-当用户达到700岁时将出现点击

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

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