2017-06-02 60 views
0

检测至少1记录的存在,我有两个表:MySQL的:在大连接表

用户(ID,姓名)

user_activities(ID,USER_ID,ACTIVITY_ID,created_at)

的user_activities表非常大,有超过3亿行。

我正在尝试检测哪些用户在给定日期范围内完成了任何活动。换句话说,用户表上的行,在某个created_at范围内的user_activities表上存在联合行。

我可以用INNER JOIN,GROUP BY和WHERE子句做这件事,但查询运行了很长时间,因为我相信它在我的日期范围之间触及所有user_activities行。

我并不在乎“有多少”活动,就像他们已经超过零。所以我分组得到一个计数(例如210个活动),实际上我可以在找到1后停下来。

是否有更有效的方法来执行此操作,而不是将所有user_activity行分组来计数它们?

有关的信息,这里的当前查询,工作正常,但需要较长的时间:提前

SELECT u.id, u.name, COUNT(ua.id) AS activity_count 
FROM users u 
INNER JOIN user_activity ua ON u.id=ua.user_id 
WHERE ua.created_at > '2017-01-01' AND ua.created_at < '2017-03-01' 
GROUP BY u.id 
HAVING activity_count > 0; 

谢谢!

+2

没有HAVING需要在这里,没有活动没有用户会包括在内。 (即,activity_count将总是大于0.) – jarlh

+0

所以我可以删除COUNT(ua.id)呢? – infaddict

+0

您是否需要对每个用户的活动进行计数,或者只需知道用户是否活动就足够了(即在日期范围内至少有一项活动)? –

回答

1

你可以试试这个版本:

SELECT u.id, u.name, 
     (SELECT COUNT(*) 
     FROM user_activity ua 
     WHERE u.id = ua.user_id AND 
       ua.created_at > '2017-01-01' AND 
       ua.created_at < '2017-03-01' 
     ) as activity_count 
FROM users u 
HAVING activity_count > 0; 

对于性能你想在user_activity(user_id, created_at)的索引。

编辑:

如果你只是想生存,然后用同样的指标,这应该是要快得多:

SELECT u.id, u.name 
FROM users u 
WHERE EXISTS (SELECT 1 
       FROM user_activity ua 
       WHERE u.id = ua.user_id AND 
        ua.created_at > '2017-01-01' AND 
        ua.created_at < '2017-03-01' 
      ); 

而您的查询做复杂处理,然后一组数据的汇总,这应该扫描users表,并在索引中查找用户是否存在适当的活动。

+0

非常感谢Gordon,你的第二个查询正是我想要的! – infaddict

+0

看到你在预测分析方面的一些工作,我想你可能会挖掘这一点。麻省理工学院已经发布了一些AI的讲座。开始有点慢,但它变得更好。 http://www.openculture.com/2017/05/artificial-intelligence-a-free-online-course-from-mit.html ... –

+0

@JohnCappelletti。 。 。作为一名大学生,我从帕特里克温斯顿到麻省理工学院学习了我的AI课程。我不会在公共论坛上发表我的评论;) –

1

使用EXISTS子句,因此DBMS认为只需在给定的日期范围内为每个用户查找一条记录即可。

SELECT id, name 
FROM users u 
where exists 
(
    select * 
    from user_activity ua 
    where ua.user_id = u.id 
    and ua.created_at > '2017-01-01' AND ua.created_at < '2017-03-01' 
); 

有了这个指数:

create index idx on user_activity(user_id, created_at); 
0

为了让谁做活动,在指定日期范围

select u.id, u.name from users u 
    where exists (SELECT 1 FROM user_activity ua 
     where ua.user_id = u.id 
     and ua.created_at > '2017-01-01' AND 
       ua.created_at < '2017-03-01') 

创建user_activity(created_at)指数

0

如果用户其仅用于测试存在,则:

SELECT EXISTS(
    SELECT u.id 
     FROM user_activity AS ua 
     WHERE u.id = ua.user_id 
      AND ua.created_at > '2017-01-01' 
      AND ua.created_at < '2017-03-01' 
) AS ret 

这将简单的返回列 RET = 1 如果至少查询将满足给定条件的行,否则它会返回列 RET = 0