'IN / ALL / ANY'子查询中的未知列

时间:2014-03-04 22:32:45

标签: mysql sql join subquery

我有2个表:members和member_logs。

成员可以属于成员表中的组。给定一个日期范围和一个组,我试图弄清楚如何获得成功登录次数最多的10天。到目前为止,我所拥有的是一个庞大的子查询恐怖之巢。

SELECT count(member_id) AS `num_users`,
DATE_FORMAT(`login_date`,'%Y-%m-%d') AS `reg_date` 
FROM member_logs 
WHERE `login_success` = 1 
and `reg_date` IN 
    (SELECT DISTINCT DATE_FORMAT(`login_date`,'%Y-%m-%d') AS `reg_date` 
     FROM member_logs 
     WHERE `login_success` = 1 
     and (DATE_FORMAT(`login_date`,'%Y-%m-%d') BETWEEN '2012-02-25' and '2014-03-04'))
and `member_id` IN 
    (SELECT `member_id` 
     FROM members 
     WHERE `group_id` = 'XXXXXXX' 
     and `deleted` = 0) 
ORDER BY `num_users` desc 
LIMIT 0, 10

据我所知,发生的事情是WHERE子句在子查询生成之前进行评估,而且我也应该使用连接。如果有人可以帮助我,或指出我的方向是不可思议的。

编辑:限制错了,修好了

3 个答案:

答案 0 :(得分:3)

第一个子查询完全没必要,因为您可以直接在当前表member_logs中按日期过滤。我也更喜欢第二个子查询的JOIN。然后你缺少的是按日期(日)分组。

如下所示的查询(未经测试)将完成您想要的工作:

SELECT COUNT(ml.member_id) AS `num_users`, 
  DATE_FORMAT(`login_date`,'%Y-%m-%d') AS `reg_date` 
FROM member_logs ml
INNER JOIN members m ON ml.member_id = m.member_id
WHERE `login_success` = 1 
  AND DATE_FORMAT(`login_date`,'%Y-%m-%d') BETWEEN '2012-02-25' AND '2014-03-04'
  AND `group_id` = 'XXXXXXX' 
  AND `deleted` = 0 
GROUP BY `reg_date`
ORDER BY `num_users` desc 
LIMIT 10

答案 1 :(得分:0)

SELECT count(member_id) AS `num_users`,
DATE_FORMAT(`login_date`,'%Y-%m-%d') AS `reg_date` 
FROM member_logs 
WHERE `login_success` = 1 
and `login_date` IN 
    (SELECT `login_date` 
     FROM member_logs 
     WHERE `login_success` = 1 
     and (DATE_FORMAT(`login_date`,'%Y-%m-%d') BETWEEN '2012-02-25' and '2014-03-04'))
and `member_id` IN 
    (SELECT `member_id` 
     FROM members 
     WHERE `group_id` = 'XXXXXXX' 
     and `deleted` = 0) 
Group by `login_date`
ORDER BY `num_users` desc 
LIMIT 0, 10

答案 2 :(得分:0)

作为之前答案的索引友好版本;

要使查询索引友好,不应在搜索条件中按行计算。此查询会删除WHERE中字符串格式日期的每行计算,因此如果按日期范围消除许多行,则应该更快;

SELECT COUNT(*) num_users, DATE(login_date) reg_date
FROM member_logs JOIN members ON member_logs.member_id = members.member_id
WHERE login_success = 1 AND group_id = 'XXX' AND deleted = 0 
  AND login_date >= '2012-02-25' 
  AND login_date < DATE_ADD('2014-03-04', INTERVAL 1 DAY)
GROUP BY DATE(login_date)
ORDER BY num_users DESC 
LIMIT 10