2015-01-23 2 views
3

이 문제를 처리하는 몇 가지 질문을 발견했으며 MySQL은이를 허용하지 않습니다. 괜찮아요, 난 FROM 절에 하위 쿼리가 있어야하지 않습니다. 그러나 나는 그걸 해결하는 방법을 모른다. 여기에 내 설치가 :FROM 절의 SQL 하위 쿼리

내가 원하는 3 개의 열이있는 메트릭스 테이블이 있습니다 : ControllerID, TimeStamp 및 State. 기본적으로 데이터 수집 엔진은 5 분마다 데이터베이스의 각 컨트롤러에 연결하고 메트릭 테이블에 항목을 저장합니다. 표에는이 세 개의 열과 MetricID가 포함되어 있습니다. 어쩌면 그 통계를 저장하는 더 좋은 방법이 있을지 모르지만 나는 그것을 모른다. 상관없이 각기 다른 ControllerID에 대해 가장 최근의 TimeStamp를 가져 와서 TimeStamp, ControllerID 및 State를 가져 오는보기가 필요합니다. 따라서 4 개의 컨트롤러가있는 경우보기에는 항상 가장 최근의 상태와 함께 다른 컨트롤러가있는 4 개의 행이 있어야합니다.

나는 원하는 것을 얻는 쿼리를 만들 수 있었지만 FROM 절의 하위 쿼리에 의존합니다. 뷰에서 허용되지 않는 쿼리입니다. 여기 내가 지금까지 가지고있는 것입니다 :

SELECT * 
FROM 
    (SELECT 
    ControllerID, TimeStamp, State 
    FROM Metrics 
    ORDER BY TimeStamp DESC) 
AS t 
GROUP BY ControllerID; 

내가 말했듯이,이 훌륭한 작품. 하지만 나는 그것을보기에 사용할 수 없다. max() 함수를 사용해 보았습니다. 그러나 여기서는 다음과 같습니다. SQL: Any straightforward way to order results FIRST, THEN group by another column? GROUP BY 및 ORDER BY 열 외에 추가 열을 원하면 max()가 작동하지 않습니다. 이 제한 사항을 확인했지만 작동하지 않습니다.

또한 타임 스탬프로 주문하기 위해 메트릭 테이블을 변경하려고했습니다. 그것도 작동하지 않습니다; 잘못된 행이 유지됩니다.

편집 : 여기에서 당겨 오전 메트릭 테이블의 SHOW CREATE TABLE입니다 :

CREATE TABLE Metrics (
    MetricsID int(11) NOT NULL AUTO_INCREMENT, 
    ControllerID int(11) NOT NULL, 
    TimeStamp timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, 
    State tinyint(4) NOT NULL, 
    PRIMARY KEY (MetricsID), 
    KEY makeItFast (ControllerID,MetricsID), 
    KEY fast (ControllerID,TimeStamp), 
    KEY fast2 (MetricsID), 
    KEY MetricsID (MetricsID), 
    KEY TimeStamp (TimeStamp) 
) ENGINE=InnoDB AUTO_INCREMENT=8958 DEFAULT CHARSET=latin1 
+0

쿼리에서 새 테이블을 만들고 트리거를 추가하여 필요한 간격으로 업데이트를 유지하고보기에서 사용합니다. – Mihai

+0

불행히도 참조 된 대답은 분명히 문서화 된 MySQL 확장을 사용하기 때문에 올바르지 않습니다. 쿼리가 작동하는 데 필요한 결과를 반환하지 않으려면 http://dev.mysql.com/doc/refman/5.6/en/group-by-handling.html을 참조하십시오. –

+1

예, 이것은 MySQL의 (이상한) 제한 사항 중 하나입니다. 뷰에 파생 테이블을 사용할 수 없습니다. 파생 테이블을 사용하지 않으려면 명령문을 다시 작성해야합니다. –

답변

1

편집 죄송합니다, 나는 당신의 질문을 오해; 난 당신이보기에서 중첩 쿼리 제한을 극복하기 위해 노력하고 있다고 생각.

각 ControllerID에 대해 가장 최근의 행을 표시하려고합니다. 또한, 당신은 그것을보기 위해 노력하고 있습니다.

먼저 해보 죠. MetricsID 열 (내가 신경 쓰지 않는다고 알고있는 열)이 자동 증가 열이면 정말 쉽습니다.

SELECT ControllerId, TimeStamp, State 
    FROM Metrics m 
    WHERE MetricsID IN (
       SELECT MAX(MetricsID) MetricsID 
       FROM Metrics 
       GROUP BY ControllerID) 
    ORDER BY ControllerID 

이 쿼리는 각 컨트롤러의 가장 높은 번호 (가장 최근) 행을 추출 MAX ... GROUP BY를 사용합니다. 그것은 보기로 만들 수 있습니다.

(ControllerID, MetricsID)에 대한 복합 색인은 매우 효율적인 loose index scan을 가진 부속 조회를 충족시킬 수 있습니다.

내 혼란의 근본 원인 : 귀하의 질문을 신중하게 읽지 않았습니다.

혼란의 근본 원인 : 당신은 GROUP BY에 대한 치명적인 MySQL 확장 기능을 이용하려고합니다. 하위 쿼리를 주문하는 아이디어가 효과가있을 수 있습니다. 그러나 귀하의 일시적인 성공은 현재 구현의 우발적 인 부작용입니다.이 읽기 :이 보장되지 않는 MySQL의 확장 기능을 사용하기 때문에

SELECT ControllerID, TimeStamp, State 
FROM Metrics m 
WHERE NOT EXISTS (SELECT 1 
        FROM Metrics m2 
        WHERE m2.ControllerId = m.ControllerId and m2.Timestamp > m.TimeStamp 
       ); 

조회에, 어쨌든 해결되지 않은 : 당신은 각각의 컨트롤러에 대한 가장 최근의 행을 원하는 경우, 다음과 같은 친절한보기 http://dev.mysql.com/doc/refman/5.6/en/group-by-handling.html

+0

어쩌면 나는 단지 그것을 보지 못한다. 그러나 이것이 어떻게 질문에 어떻게 대답하는지 이해할 수 없다 .... – Carrot

+0

Duh, 나는 당신의 질문을 오해했다. Pls 내 편집을 참조하십시오. –

+0

좋아요, 어떻게 작동하는지 봅니다. 그러나 실행하는 데 9 초가 걸리므로 해결할 수는 있지만 Metrics 테이블에는 ~ 8500 개의 행만 있습니다. 내가 끝내면 아마 훨씬 더 많은 것을 얻게 될거야. 쿼리가 중단되었으며 각 부분이 매우 빠르게 실행됩니다. 예 : 하위 쿼리와 함께 max (MetricID)를 모두 얻은 경우 하위 쿼리를 해당 숫자로 바꿉니다. '(SELECT ... FROM ... WHERE Metrics ID IN (8562, 8567, 5478, 5532, 8568, 8569) ', 더 빨리 실행되는 이유는 무엇입니까? 내가 할 수있는 최적화가 더 있습니까 지금까지 도움을 주셔서 감사합니다 – Carrot

2

입니다 작업. state의 값은 가장 큰 시간 소인이있는 행에서 가져올 필요는 없습니다. 그것은 임의의 행에서옵니다.

편집 :

최적의 성능을 위해, 당신은 Metrics(ControllerId, Timestamp)에 인덱스를 원한다.

+0

음, 확실히 작동합니다. 감사! 그래도 몇 가지 질문이 있습니다. 첫째,이 쿼리를 최적화 할 수있는 방법이 있습니까? 간단한 mysql 프롬프트에서 5 초 이상 걸립니다. 둘째, 초기 쿼리가 작동하지 않는 이유는 무엇입니까? 모든 결과를 주문한 다음 그룹 별을 사용하여 상단에서 시작합니다 (상단에서 시작합니까?). 그리고 모든 고유 한 컨트롤러 ID를 선택합니다. 테스트 할 때마다 효과가있는 것 같습니다. – Carrot

+0

@ 카롯. . . 하위 쿼리의 순서는'group by '에 의해'state'의 값으로 임의의 행이 선택되는 것과는 아무런 관련이 없습니다 (이론적으로). 이 값은 * indeterminate * 행에서 가져옵니다. 즉, '그룹 별'이 영향을 미칠 수 있음을 의미합니다. –

+0

굉장! 나는 지금 나는 이해한다고 생각한다. 그러나 인덱스를 사용하더라도 쿼리를 실행하는 데 3 초 이상 걸립니다. 더 이상 최적화 할 수있는 방법이 있습니까? 나는 이것이 쿼리의 강렬한 느낌이 아니며 실행하는 데 오랜 시간이 걸리지 않아야한다고 생각합니다. 다시 도움을 청합니다! – Carrot