2017-12-08 5 views
2

내 웹 사이트 영역을 손상시키는 쿼리가 있습니다. 다음 SQL 문을로드하려고 시도하면 사이트가 계속 회전합니다! 나는 SQL 문에 상당히 익숙하지 않다. 그리고이 특별한 문장은 다른 개발자에 의해 만들어졌다. 다음 진술을 최적화 할 수있는 방법이 있습니까? 또는 더 빨리 실행할 수 있도록 작은 문장으로 나누십시오. 나는 잃어 버렸다! 어떤 도움을 주셔서 감사합니다.JOIN이있는 SQL 문을 더 작은 쿼리로 분해하거나 쿼리를 최적화 할 수 있습니까?

SELECT 
    `wp_quiz_users`.`Id`, 
    `wp_quiz_users`.`SessionId`, 
    `wp_quiz_users`.`Score`, 
    `wp_quiz_users`.`Date`, 
    `wp_quiz_users`.`Referrer`, 
    `wp_quiz_users`.`ContactData`, 
    (SELECT 
     SUM(`wp_quiz_users_answers`.`AnswerValue`) 
    FROM 
     `wp_quiz_users_answers` 
    JOIN 
     `wp_quiz_questions` 
      ON `wp_quiz_users_answers`.`QuestionId` = `wp_quiz_questions`.`id` 
    WHERE 
     `wp_quiz_users_answers`.`UserId` = `wp_quiz_users`.`Id` 
     AND `wp_quiz_questions`.`Category` = 1) AS `SectionOne`, 
    (SELECT 
     SUM(`wp_quiz_users_answers`.`AnswerValue`) 
    FROM 
     `wp_quiz_users_answers` 
    JOIN 
     `wp_quiz_questions` 
      ON `wp_quiz_users_answers`.`QuestionId` = `wp_quiz_questions`.`id` 
    WHERE 
     `wp_quiz_users_answers`.`UserId` = `wp_quiz_users`.`Id` 
     AND `wp_quiz_questions`.`Category` = 2) AS `SectionTwo`, 
    (SELECT 
     SUM(`wp_quiz_users_answers`.`AnswerValue`) 
    FROM 
     `wp_quiz_users_answers` 
    JOIN 
     `wp_quiz_questions` 
      ON `wp_quiz_users_answers`.`QuestionId` = `wp_quiz_questions`.`id` 
    WHERE 
     `wp_quiz_users_answers`.`UserId` = `wp_quiz_users`.`Id` 
     AND `wp_quiz_questions`.`Category` = 3) AS `SectionThree`, 
    (SELECT 
     SUM(`wp_quiz_users_answers`.`AnswerValue`) 
    FROM 
     `wp_quiz_users_answers` 
    JOIN 
     `wp_quiz_questions` 
      ON `wp_quiz_users_answers`.`QuestionId` = `wp_quiz_questions`.`id` 
    WHERE 
     `wp_quiz_users_answers`.`UserId` = `wp_quiz_users`.`Id` 
     AND `wp_quiz_questions`.`Category` = 4) AS `SectionFour`, 
    (SELECT 
     SUM(`wp_quiz_users_answers`.`AnswerValue`) 
    FROM 
     `wp_quiz_users_answers` 
    JOIN 
     `wp_quiz_questions` 
      ON `wp_quiz_users_answers`.`QuestionId` = `wp_quiz_questions`.`id` 
    WHERE 
     `wp_quiz_users_answers`.`UserId` = `wp_quiz_users`.`Id` 
     AND `wp_quiz_questions`.`Category` = 5) AS `SectionFive` 
FROM 
    `wp_quiz_users` 
+0

해당 검색어는 미친 듯합니다. 나중에 참조 할 때 쿼리는 그렇게 보이지 않습니다. 동일한 테이블을 반복해서 언급하는 쿼리를 의심하십시오. –

답변

5

이 답변이 별도의 하위 쿼리 내부의 총액에 대한 집계를 수행하는 것을 제외하고는 고든과 유사하다. 이렇게하면 외부 쿼리를 집계 할 필요가 없으므로 wp_quiz_users 테이블에서 원하는 열을 선택하는 데 아무런 문제가 없어야합니다.

SELECT 
    t1.Id, 
    t1.SessionId, 
    t1.Score, 
    t1.Date, 
    t1.Referrer, 
    t1.ContactData, 
    COALESCE(t2.SectionOne, 0) AS SectionOne, 
    COALESCE(t2.SectionTwo, 0) AS SectionTwo, 
    COALESCE(t2.SectionThree, 0) AS SectionThree, 
    COALESCE(t2.SectionFour, 0) AS SectionFour, 
    COALESCE(t2.SectionFive 0) AS SectionFive 
FROM wp_quiz_users t1 
LEFT JOIN 
(
    SELECT 
     t1.UserId, 
     SUM(CASE WHEN t2.Category = 1 THEN t1.AnswerValue ELSE 0 END) AS SectionOne, 
     SUM(CASE WHEN t2.Category = 2 THEN t1.AnswerValue ELSE 0 END) AS SectionTwo, 
     SUM(CASE WHEN t2.Category = 3 THEN t1.AnswerValue ELSE 0 END) AS SectionThree, 
     SUM(CASE WHEN t2.Category = 4 THEN t1.AnswerValue ELSE 0 END) AS SectionFour, 
     SUM(CASE WHEN t2.Category = 5 THEN t1.AnswerValue ELSE 0 END) AS SectionFive 
    FROM wp_quiz_users_answers t1 
    INNER JOIN wp_quiz_questions t2 
     ON t1.QuestionId = t2.id 
    GROUP BY t1.UserId 
) t2 
    ON t1.Id = t2.UserId; 
+0

. .MySQL이나 ANSI SQL ('id' 컬럼이 유일하다는 가정하에)에서 users 테이블의 모든 컬럼을 선택하는 데 아무런 문제가 없습니다. ANSI SQL은 집계에 고유 키가 사용될 때 데이터베이스가 행에서 모든 열을 선택하도록 허용합니다. –

+0

@ GordonLinoff 네,이 사실을 압니다. 나는 어떤 이유로 'Id' 칼럼이 프라이 머리 키 칼럼이 아니라면 편집증에 빠졌습니다. 또는 아마도 나중에 리팩터러가 이것을 바꿀 수도 있습니다. –

+0

@TimBiegeleisen 정말 고마워요 !! 당신은 기적의 제작자입니다. 나는이 진술을 며칠 동안 해킹했다. – Christy

1

난 그냥 조건부 집계를 원한다고 생각 :

SELECT qu.*, 
     SUM(CASE WHEN qq.Category = 1 THEN qa.AnswerValue END) as SectionOne, 
     SUM(CASE WHEN qq.Category = 2 THEN qa.AnswerValue END) as SectionTwo, 
     SUM(CASE WHEN qq.Category = 3 THEN qa.AnswerValue END) as SectionThree, 
     SUM(CASE WHEN qq.Category = 4 THEN qa.AnswerValue END) as SectionFour, 
     SUM(CASE WHEN qq.Category = 5 THEN qa.AnswerValue END) as SectionFive 
FROM wp_quiz_users qu LEFT JOIN 
    wp_quiz_users_answers qa 
    ON qa.UserId = q.id LEFT JOIN 
    wp_quiz_questions qq 
    ON qa.QuestionId = qq.id 
GROUP BY qu.UserId; 
+0

왜 이것을 다운 그레이드하겠습니까? –

+0

나는 downvote에 반대했다. 나는 또한 이것이 왜 왜곡되었는지 알지 못한다. –

1

이것은 Gordon Linoff와 비슷하지만 어느 시점에서 필요 할지도 모르는 구문에 대한 설명을 추가하려고합니다. SQL의 표준 동작은 집계 함수를 포함하지 않는 모든 열 [예 : sum()]은 group by 절에 나열되어야합니다.

SELECT 
     wp_quiz_users.Id 
    , wp_quiz_users.SessionId 
    , wp_quiz_users.Score 
    , wp_quiz_users.Date 
    , wp_quiz_users.Referrer 
    , wp_quiz_users.ContactData 
    , SUM(CASE WHEN qq.Category = 1 THEN qa.AnswerValue END) AS sectionone 
    , SUM(CASE WHEN qq.Category = 2 THEN qa.AnswerValue END) AS sectiontwo 
    , SUM(CASE WHEN qq.Category = 3 THEN qa.AnswerValue END) AS sectionthree 
    , SUM(CASE WHEN qq.Category = 4 THEN qa.AnswerValue END) AS sectionfour 
    , SUM(CASE WHEN qq.Category = 5 THEN qa.AnswerValue END) AS sectionfive 
FROM wp_quiz_users qu 
LEFT JOIN wp_quiz_users_answers qa ON qa.UserId = q.id 
LEFT JOIN wp_quiz_questions qq ON qa.QuestionId = qq.id 
GROUP BY 
     wp_quiz_users.Id 
    , wp_quiz_users.SessionId 
    , wp_quiz_users.Score 
    , wp_quiz_users.Date 
    , wp_quiz_users.Referrer 
    , wp_quiz_users.ContactData 
; 

즉 그것은 또한 모든 사용자가 select 절에 필요한 열, 또한 GROUP BY 절에 나열된 모든 "비 집계"열을 나열하는 것이 좋습니다.

쿼리는 다음과 같이 사용을 참조 :

select * from sometable group by name 

는 그런 다음 쿼리하거나 해제 할 수있는 표준이 아닌 MySQL의 확장 기능을 사용합니다. 해당 확장이 꺼져 있으면 확장에 의존하는 쿼리가 실패하기 시작합니다. 따라서 신중한 코더는 group by 절에 모든 비 집합 열을 나열하여 잠재적 인 문제를 피할 수 있습니다. 참조 : https://dev.mysql.com/doc/refman/5.7/en/group-by-modifiers.html


을 당신이 성능을 위해 끔찍한 것을 발견했다 select 절 내부와 같이 많은 "상관 하위 쿼리"를 포함하는 원래의 질의에 대해서. 어떤것는 대부분의 시간을 피할 수있는 동안 우리가 전혀 사용하지 않습니다 말할 수 없다, 그래서 그들은 괜찮은 옵션이 될 수 있습니다 때때로 그러나 이러한

select name 
    , (select sum(value) from tablex 
     where tablex.id = table1.id -- the "correlation" of tablex to table1 is here 
    ) 
from table1 

에 대한 경계해야합니다.

+0

이것은 완전히 정확하지 않습니다. 키 열을 기준으로 집계하는 경우 해당 키에 기능적으로 종속 된 열은 'GROUP BY'에 추가하지 않고 선택할 수 있습니다. –

+0

"should"는 "must"가 아님을 유의하십시오. 나는 당신이 (충분히 알고 있다면) "기능적 의존"에 의지 할 수 있다는 것을 알고있다. 그러나 이것은 신규 이민자에게 항상 분명하거나 이해하기 쉬운 것은 아닙니다. 내가 전달하고자하는 것은 비표준 구문에 대한 의존성이 문제로 이어질 수 있다는 것입니다. –

+0

나는 동의한다. 그래서 나는 +1 한 대답을 게시했다. –

0

나는

FROM (
     SELECT ua.`UserId`, 
       q.Category, 
       SUM(ua.`AnswerValue`) 
      FROM `wp_quiz_users_answers` AS ua 
      JOIN `wp_quiz_questions` AS q 
       ON ua.`QuestionId` = q.`id` 
      GROUP BY ua.`UserId`, q.Category 
     ) AS x 
    JOIN wp_quiz_users AS u 
     ON u.Id = x.UserId 

시작 것이고 그것의 주위에 구축. 또는 다른 방법 - - SUMs 인해 팽창 할 것이다 나의 접근 방식은 경우

(. 내가 다른 답변을 참조하지만 이후, 나는 게으른이 생각을 완료 할 수 있습니다)

는 흠 ... 궁금 너무 늦게 기다려서 GROUP BY ??