2010-01-11 7 views
7

나는 그들이 제출 한 서평 및 조리법 리뷰의 수에 따라 사이트 사용자를 순위 매기기 위해 MySQL 쿼리를 실행하고 있습니다. 다중 JOIN 쿼리의 초기 문제 이후에 나는 훨씬 더 빨라진 일련의 하위 쿼리로 전환했습니다. 그러나 각 회원의 리뷰 수를 추출 할 수는 있지만 총계를 기준으로 정렬 할 수 있도록 함께 추가하는 방법을 알 수는 없습니다.여러 개의 하위 쿼리 결과를 함께 추가하는 방법은 무엇입니까?

SELECT users.*, 
    (SELECT count(*) FROM bookshelf WHERE bookshelf.user_id = users.ID) as titles, 
    (SELECT count(*) FROM book_reviews WHERE book_reviews.user_id = users.ID) as bookreviews, 
    (SELECT count(*) FROM recipe_reviews WHERE recipe_reviews.user_id = users.ID) as recipereviews 
FROM users 

내가 'reviewtotals'를 얻기 위해서 함께 bookreviews 및 recipereviews을 추가해야합니다

여기에 현재 쿼리입니다. MySQL은 간단한 구문을 사용하여 별칭에 대한 계산을 허용하지 않지만이 작업을 수행 할 다른 방법이 있습니까?

+0

@mandel - 내 대답을 참조하십시오 나는이 매우 특별한 경우에 안전합니다 예측 참고. 제 경험상 대개 MySQL과 관련하여 여러 개의 상관 관계가있는 서브 쿼리보다 훨씬 빠릅니다. 나는 당신의 경우 서브 쿼리 솔루션이 JOIN보다 빠르다는 것을 듣고 싶다. 네가 내게 알려주면 많이 감사 할께. –

+0

JOIN의 문제점은 철학보다는 미숙 한 경험에서 비롯된 것입니다. 이전의 JOIN 결과는 9 초였습니다. 카티 시안 (Cartesian) 제품을 만드는 것으로 밝혀졌습니다. 나는 그것에 대해 여기에서 물었다 : http://stackoverflow.com/questions/2030032/is-performing-a-count-calculation-slowing-down-my-mysql-query. 서브 쿼리를 사용하는 것으로 바뀌었을 때 속도가 크게 향상되었으며 내가하는 일을 이해할 수있었습니다. – mandel

+0

속도 비교를 위해 게시물에 대한 내 답변보기 - JOIN 쿼리는 현재 DB 크기에서 초당 4/100 초만 빨라졌습니다. – mandel

답변

9

이 하위 쿼리로 랩 : 당신이 안전하고 빠르게하고 싶다면

SELECT *, 
     bookreviews + recipereviews AS totalreviews 
FROM (
     SELECT users.*, 
       (SELECT count(*) FROM bookshelf WHERE bookshelf.user_id = users.ID) as titles, 
       (SELECT count(*) FROM book_reviews WHERE book_reviews.user_id = users.ID) as bookreviews, 
       (SELECT count(*) FROM recipe_reviews WHERE recipe_reviews.user_id = users.ID) as recipereviews 
     FROM users 
     ) q 
0

다음을 시도하셨습니까?

SELECT users.*, 
    (SELECT count(*) FROM bookshelf WHERE bookshelf.user_id = users.ID) as titles, 
    ((SELECT count(*) FROM book_reviews WHERE book_reviews.user_id = users.ID) + 
    (SELECT count(*) FROM recipe_reviews WHERE recipe_reviews.user_id = users.ID)) as reviewtotal 
FROM users 
+0

고마워요. 거의 다 됐습니다.하지만 여전히 계산 된 합계뿐 아니라 bookreviews와 recipereviews에서 총계를 생성해야합니다. – mandel

1

두 가지 옵션 :

옵션 1 :

SELECT users.*, 
    (SELECT count(*) FROM bookshelf WHERE bookshelf.user_id = users.ID) as titles, 
    (SELECT count(*) FROM book_reviews WHERE book_reviews.user_id = users.ID) as bookreviews, 
    (SELECT count(*) FROM recipe_reviews WHERE recipe_reviews.user_id = users.ID) as recipereviews 
    (SELECT count(*) FROM book_reviews WHERE book_reviews.user_id = users.ID) + (SELECT count(*) FROM recipe_reviews WHERE recipe_reviews.user_id = users.ID) as reviewtotals 
FROM users 

옵션 2 : 미운 지옥, 아마도 느린 (쿼리 캐시에 따라 다름)입니다 임시 테이블에 결과를 저장하고 다음 표는 작동 아마도

를 조회

SELECT *, bookreviews+recipereviews as reviewtotals FROM 
(SELECT users.*, 
    (SELECT count(*) FROM bookshelf WHERE bookshelf.user_id = users.ID) as titles, 
    (SELECT count(*) FROM book_reviews WHERE book_reviews.user_id = users.ID) as bookreviews, 
    (SELECT count(*) FROM recipe_reviews WHERE recipe_reviews.user_id = users.ID) as recipereviews 
FROM users) u 
0 (그것을 시도하지 않은)
+0

Number 2는 거의 작동하지만 첫 번째 하위 쿼리에 별칭을 추가해야합니다. 그러나 1 분 전인 @ Quassnoi의 솔루션과 동일합니다. 감사! – mandel

+0

타이핑 중에 다른 대답이있는 것을 보았습니다 ... –

1

는, 이런 식으로 작업을 수행합니다

SELECT users.* 
,  titles.num       titles 
,  book_reviews.num      book_reviews 
,  recipe_reviews.num     recipe_reviews 
,  book_reviews.num + recipe_reviews.num total_reviews 
FROM  users 
LEFT JOIN (
      SELECT user_ID, count(*) AS num 
      FROM  bookshelf 
      GROUP BY user_ID 
     ) as titles 
ON  users.ID = titles.user_ID 
LEFT JOIN (
      SELECT user_ID, count(*) AS num 
      FROM  book_reviews 
      GROUP BY user_ID 
     ) as book_reviews 
ON  users.ID = reviews.user_ID 
LEFT JOIN (
      SELECT user_ID, count(*) AS num 
      FROM  recipe_reviews 
      GROUP BY user_ID 
     ) as recipe_reviews 
ON  users.ID = recipes.user_ID 

당신이 SELECT 목록에있는 하위 쿼리에 충실하려면, Quassnoi의 솔루션을 살펴보십시오.

dangersouly로 살기를 원하고 빠른 결과를 원하면 사용자 정의 변수를 사용할 수 있습니다. 나는 JOIN` 일반적으로, 나는`JOIN`으로 이런 종류의 문제를 해결`와 문제에 대한 궁금

SELECT users.*, 
     (SELECT count(*) FROM bookshelf WHERE bookshelf.user_id = users.ID) as titles, 
     @bookreviews:=(
      SELECT count(*) 
      FROM book_reviews 
      WHERE book_reviews.user_id = users.ID 
     ) as bookreviews, 
     @recipereviews:=(
      SELECT count(*) 
      FROM recipe_reviews 
      WHERE recipe_reviews.user_id = users.ID 
     ) as recipereviews, 
     @bookreviews + @recipereviews as total_reviews 
FROM users 
+0

흥미 롭습니다 : 옵션 1은 Quassnoi의 솔루션보다 약간 빠릅니다 (0.02 초 vs 0.024 초), 옵션 2는 0.88 초이므로 상대적으로 약간 느립니다. 나는 Quassnoi가 가독성 측면에서 훨씬 단순하다는 것을 발견했다. 첫 번째 예제에서 JOIN 메서드를 사용하면 장점이 있습니까? – mandel

+0

mandel : 네, 다루는 세트가 커지면 이점이 빨리 분명 해집니다. JOIN은 확장 성이 훨씬 뛰어납니다. 그러나,이 시계 시간에, 나는 우리가 결정적인 것을 말할 수 있다고 생각하지 않습니다. 나는 그런 작은 차이를 무시할 것이다. 그러나 더 많은 데이터를 처리해야 할 때 상당한 차이가 있음을 알 수 있습니다. 하위 쿼리 솔루션은 외부 쿼리의 각 행에 대해 각 하위 쿼리를 실행합니다. 일반적으로 중첩 루프 조인이 훨씬 더 효율적입니다. –

관련 문제