【问题标题】:Unknown Column in 'IN/ALL/ANY' subquery“IN/ALL/ANY”子查询中的未知列
【发布时间】:2014-04-06 17:36:36
【问题描述】:

我有 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 子句在子查询生成之前进行评估,我也应该使用连接。如果有人可以帮助我或为我指明正确的方向,那将是不可思议的。

编辑:限制错误,已修复

【问题讨论】:

  • 您的实际问题是什么?
  • @Strawberry 我在当前结构中犯了哪些错误,如何通过连接来解决?
  • 第一部分太无聊了。对于第二部分,考虑提供适当的 DDL(和/或 sqlfiddle)以及所需的结果集

标签: mysql sql join subquery


【解决方案1】:

第一个子查询完全没有必要,因为您可以直接在当前表 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 不测试代码并让我修补
【解决方案2】:
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

【讨论】:

    【解决方案3】:

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

    为了使查询索引友好,您不应该在搜索条件中进行每行计算。这个查询去掉了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
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2017-11-14
      • 1970-01-01
      • 2015-03-07
      • 2022-01-06
      • 2013-07-27
      • 2013-10-21
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多