MySQL多个Date子查询

时间:2011-07-26 10:56:44

标签: mysql indexing query-optimization subquery

我正在根据项目的特定关系为包含可变数量列的特定报告编写查询。如果需要,我对如何更改查询的建议持开放态度,但我认为不可以。我宁愿将其保留为单个查询,而不是在循环中运行它。正在搜索的表包含大约400万条记录,无法存档。

我想知道的是,为什么DATEADD索引没有在子查询上使用,尽管它在外部查询中使用,它位于同一个表中。我知道一个字段上的函数阻止MySQL能够索引,但这只是在项目上,而不是你要比较它。

报告的结果是每个特定项目(子查询)的数字,表示范围内的每个日期。日期范围是动态生成的。 subquerys应该返回一天的结果

我们使用的是MySQL版本5.0.77,我们无法更改,因为它由我们的托管服务提供商管理。

以下是查询:

 SELECT DATE_FORMAT(DATEADD, '%d/%m/%y') AS DATEADD,

   (SELECT COUNT(ID)
      FROM ATABLE AS 
     WHERE ELEMNAME = 'ANELEMENT' AND COMPID = 132
           AND VT.DATEADD BETWEEN CONCAT(DATE(V.DATEADD)," 00:00:00") AND CONCAT(DATE(V.DATEADD)," 23:59:59")))
      AS '132',

   (SELECT COUNT(ID)
      FROM ATABLE AS 
     WHERE ELEMNAME = 'ANELEMENT' AND COMPID = 149
           AND VT.DATEADD BETWEEN CONCAT(DATE(V.DATEADD)," 00:00:00") AND CONCAT(DATE(V.DATEADD)," 23:59:59")))
      AS '149'

 FROM ATABLE AS V
WHERE 1 = 1 AND COMPID = 132
   AND (V.DATEADD >= "2010-09-01 00:00:00"
        AND V.DATEADD <= "2010-10-26 23:59:59")
   AND 1 = 1
   AND ELEMNAME = 'ANELEMENT'
GROUP BY DATE_FORMAT(DATEADD, '%Y-%m-%d')

子查询的运行次数取决于此项具有的链接数,并在构建查询时确定。

我们尝试过: 用

代替
"VT.DATEADD <= DATE(V.DATEADD) and VT.DATEADD <= DATE(V.DATEADD) +1" 

然而这也无效,将其改为

"VT.DATEADD = DATE(V.DATEADD)" 

确实使用了索引,但是没有返回正确的行数,因为DATEADD是一个日期时间。如果我们将其更改为:

"VT.DATEADD >= "2010-09-01" AND VT.DATEADD <= "2010-09-02"

Explain的输出是

+----+--------------------+-------+-------+-------------------------+----------+---------+-------+-------+----------------------------------------------+
| id | select_type        | table | type  | possible_keys           | key      | key_len | ref   | rows  | Extra                                        |
+----+--------------------+-------+-------+-------------------------+----------+---------+-------+-------+----------------------------------------------+
|  1 | PRIMARY            | V     | range | DATEADD,COMPID,ELEMNAME | DATEADD  | 8       | NULL  |  1386 | Using where; Using temporary; Using filesort |
|  2 | DEPENDENT SUBQUERY | VT    | ref   | COMPID,ELEMNAME         | ELEMNAME | 103     | const | 44277 | Using where                                  |
+----+--------------------+-------+-------+-------------------------+----------+---------+-------+-------+----------------------------------------------+

使用USE INDEX或FORCE INDEX(当它可用但未使用时)使用NULL键

如果不解决这个问题,即使在很小的日期范围内,查询也会非常缓慢地运行并锁定数据库。

1 个答案:

答案 0 :(得分:0)

我不知道我是否过度简化了你想要的整体,但这个对你有用。您似乎想知道给定日期范围内两个“compid”值的活动量。

SELECT 
      DATE_FORMAT(DATEADD, '%Y-%m-%d'),
      SUM( if( compid = 132, 1, 0 ) ) as Count132,
      SUM( if( compid = 149, 1, 0 ) ) as Count149
   from
      ATable 
   where
          elemname = "ANELEMENT"
      AND ( compid = 132 or compid = 149 )
      AND DATEADD BETWEEN "2010-09-01 00:00:00" AND "2010-10-26 23:59:59"
   group by
      dateadd