2011-07-26 11 views
1

항목의 특정 관계를 기반으로 다양한 수의 열을 포함하는 매우 구체적인 보고서에 대한 쿼리를 작성하고 있습니다. 필요하다면 쿼리를 변경하는 방법에 대해서는 suggetions에 대해 공개적으로 생각하고 있지만 생각할 수는 없습니다. 루프에서 실행하는 것과는 반대로이 쿼리를 단일 쿼리로 유지하는 것이 좋습니다. 검색중인 테이블에는 약 4 백만 개의 레코드가 포함되어 있으므로 아카이브 할 수 없습니다.MySQL 다중 날짜 하위 쿼리

내가 알고 싶은 것은 같은 테이블에있는 외부 쿼리에서 사용되고 있지만 DATEADD 인덱스가 하위 쿼리에 사용되지 않는 이유입니다. 필자는 필드의 기능으로 인해 MySQL이 색인을 생성 할 수 없게되지만이 항목은 항목을 비교하는 것이 아니라 항목에만 적용된다는 것을 알고 있습니다.

보고서의 결과는 해당 범위의 각 날짜에 대해 특정 항목 (하위 쿼리)에 대한 숫자입니다. 기간은 동적으로 생성됩니다. 하위 쿼리는 하루 동안 결과를 반환해야합니다.

우리는 호스팅 공급자가 관리하는대로 변경할 수없는 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" 

설명의 출력은 수정없이 사용 INDEX 또는 FORCE 지수 (그것을 사용할 때 사용되지 않음) 사용 NULL 키

를 사용

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

입니다 이 쿼리는 매우 작은 기간 동안조차도 매우 느리게 실행되고 데이터베이스를 잠급니다.

답변

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

죄송합니다. 신속한 후속 조치를 통해 다른 게시판에서 "평판을 주어야합니다"또는 그와 같은 것을 보았습니다. 어떻게해야합니까? 자동 응답이 필요하면 답변을 수락해야합니까? –