2011-07-26 71 views
1

我正在根据项目的特定关系为包含可变数量的列的非常特定的报表撰写查询。如果需要的话,我很乐意提供如何更改查询的建议,但我不认为它可以。我宁愿将它保留为单个查询,而不是在循环中运行它。正在搜索的表格包含大约400万条记录,并且无法归档。MySQL多个日期子查询

我想知道的是,为什么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" 

从解释输出

+----+--------------------+-------+-------+-------------------------+----------+---------+-------+-------+----------------------------------------------+ 
| 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

我不知道我是不是过分地简化了你想要的东西,但是这个会为你工作。看起来你想知道给定日期范围内两个“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 
+0

根本不过分简化。事实上,它是现货!非常感谢,由于某种原因,我和另一位程序员今天早上一直在为此工作几个小时,因此我们的思想陷入了子查询模式。我们都说了一些类似“DOH !!”的话 –

+0

@Zack Newsham,我一直与Doooohhhhh一起打了很多次!!!! – DRapp

+0

对不起,只是一个快速的跟进,我在另一篇文章中看到我应该“给你声望”或其他一些,但我该怎么做,我只需要接受你的答案,自动发生? –