2013-07-09 10 views
2

테이블을 정렬하려고합니다 (부모라고 부르겠습니다). 두 테이블에 대한 관계의 수로 Child1 및 Child2라고 부릅니다. 지금은 이런 식으로 일을 해요 :여러 하위 쿼리의 합

SELECT Master.id 
(SELECT COUNT(*) FROM Child1 WHERE Child1.id=Master.id) 
+ (SELECT COUNT(*) FROM Child2 WHERE Child2.id=Master.id) AS score 
ORDER BY score DESC; 

이 예상대로 작동하지만이 하위 쿼리의 중간 값이 무엇인지 알 방법이 없기 때문에 유지 보수가 어렵다. 내가하고 싶은 것은 다음과 같다.

SELECT Master.id 
(SELECT COUNT(*) FROM Child1 WHERE Child1.id=Master.id) AS child1_score, 
(SELECT COUNT(*) FROM Child2 WHERE Child2.id=Master.id) AS child2_score, 
child1_score + child2_score AS score 
ORDER BY score DESC; 

그러나 이것은 child1_score와 child2_score가 정의되어 있지 않다는 에러를 낸다. 나는이 일을 생각할 수있는 유일한 깨끗한 방법은 중첩 된 서브 쿼리의 추가 수준이다

SELECT child1_score + child2_score AS score, id FROM 
    (SELECT Master.id 
    (SELECT COUNT(*) FROM Child1 WHERE Child1.id=Master.id) AS child1_score, 
    (SELECT COUNT(*) FROM Child2 WHERE Child2.id=Master.id) AS child2_score) 
    ORDER BY score DESC; 

하지만 메모리에 대한 훨씬 더 될 것 같은 것을 보인다.

이 문제를 해결할 더 좋은 방법이 있습니까? MySQL을 사용하고 있지만 가능한 경우 표준 구문을 고수하고 싶습니다. 마지막으로 쿼리를 기반으로

+0

당신의 해결책은 나에게 잘 어울리는 것 같습니다. – Strawberry

답변

0

당신은 :

SELECT child1_score + child2_score AS score, id FROM 
    (SELECT Master.id 
    (SELECT COUNT(*) FROM Child1 WHERE Child1.id=Master.id) AS child1_score, 
    (SELECT COUNT(*) FROM Child2 WHERE Child2.id=Master.id) AS child2_score) 
    ORDER BY score DESC; 

날 만 SELECT 에드로 Master.idscore이 필요하다고 생각하게한다.

나는이 쿼리는 괜찮을 것 같아요

SELECT Master.id 
(SELECT COUNT(*) FROM Child1 WHERE Child1.id=Master.id) + (SELECT COUNT(*) FROM Child2 WHERE Child2.id=Master.id) AS score 
FROM Master 
ORDER BY score DESC; 
+0

그건 제가 처음 들여 쓰기 한 것과 다른 질문이었습니다. 이것은 지금은 정상적으로 작동하지만, 내가 말했듯이 서브 쿼리의 중간 값을 볼 방법이 없으므로 유지 관리가 어렵습니다. –

1

글쎄, 그것은 메모리하지 더 나쁜 - DBMS는 (특히 MySQL은)는 계획을 가지고 있으며, 즉석에서 쿼리를 최적화 기억 해요. 귀하는 귀하의 질의에 Cartesian Products를 피해야 만하지만, 귀하의 마지막 질의와 @KaeL이 제안한 것과는 큰 차이가 없습니다. 중간 별칭 child1_scorechild2_score은 내부적으로 포인터이므로 방해하지 마십시오.
결국 DBMS의 신뢰성과 성능에 의존 할 수 없다면 왜 DBMS를 사용해야할까요?

편집 : 쿼리가 실행 될 것입니다 당신이 EXPLAINhttp://dev.mysql.com/doc/refman/5.0/en/explain.html
을 필요로하는지 정확히 조사하기위한 명시 적으로 최고 수준의 쿼리를 선택하지 않고 하위 쿼리의 중간 별칭을 보존 할 수있는 방법은없는 것 같다. 하위 쿼리가 예상대로 작동하는지 테스트하는 것은 전적으로 수행되어야하며 내포 된 쿼리를 구성하고 더 나아가 EXPLAIN으로 프로파일 링하여 최적화를 수행해야합니다. 이 접근 방식은 내 프로젝트에서 잘 작동합니다.

+0

내 질문을 오해 한 것 같습니다. 나는 내부 별칭을 보존하고 싶다.이 예에서는 질문을 짧게 유지하기 위해 간단한 요약을하고 있습니다. 실제로 작업중인 쿼리는보다 복잡한 수식을 사용하므로 쿼리가 어떻게 수행되고 있는지 안정적으로 판단하려면 각 하위 쿼리의 값을 확인해야합니다. –

1

MySQL을 사용하는 것이 너무 나쁩니다. 다른 DBMS를 사용하고 있다면 WITH clause을 사용할 수 있습니다. 당신이 원하는만큼 중간 하위 쿼리를 추가 할 수 있습니다이 방법을 사용

WITH First AS (
    SELECT id, COUNT(*) AS Cnt FROM Child1 GROUP BY id 
), 
Second AS (
    SELECT id, COUNT(*) AS Cnt FROM Child2 GROUP BY id 
) 
SELECT Master.id, First.Cnt, Second.Cnt, First.Cnt+Second.Cnt as score 
    FROM Master 
    INNER JOIN First ON Master.id=First.id 
    INNER JOIN Second ON Master.id=Second.id 
    ORDER BY score DESC; 

, 당신은 (단지 마지막에) 너무 일찍 하위 쿼리에서 열을 참조 할 수 있습니다 : 그런 다음 쿼리는 다음과 같을 것이다. 불행히도 MySQL을 단독으로 사용하려고 시도하는 것을 성취 할 수있는 방법이 있는지 확신 할 수 없습니다.