我正在根据项目的特定关系为包含可变数量列的特定报告编写查询。如果需要,我对如何更改查询的建议持开放态度,但我认为不可以。我宁愿将其保留为单个查询,而不是在循环中运行它。正在搜索的表包含大约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键
如果不解决这个问题,即使在很小的日期范围内,查询也会非常缓慢地运行并锁定数据库。
答案 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