2010-06-17 2 views
0

"부모"라는 마스터 테이블과 "차일드"라는 관련 테이블이 있습니다이 업데이트 쿼리를 최적화하는 방법이 있습니까?

이제 마스터 테이블에 대해 쿼리를 실행하여 일부 값을 이와 같이 하위 테이블의 합계로 업데이트합니다.

UPDATE master m SET 
    quantity1 = (SELECT SUM(quantity1) FROM childs c WHERE c.master_id = m.id), 
    quantity2 = (SELECT SUM(quantity2) FROM childs c WHERE c.master_id = m.id), 
    count = (SELECT COUNT(*) FROM childs c WHERE c.master_id = m.id) 
WHERE master_id = 666; 

기본적으로 여러 개의 SELECT 쿼리를 동일한 결과에 적용하기 때문에 예상 한대로 작동하지만 좋은 스타일이 아닙니다. 최적화 할 수있는 방법이 있습니까? .

UPDATE master m SET (quantity1, quantity2, count) = (
    SELECT SUM(quantity1), SUM(quantity2), COUNT(*) 
     FROM childs c WHERE c.master_id = m.id 
) WHERE master_id = 666; 

하지만이 작동하지 않습니다

업데이트 : (첫번째 쿼리를 만들고 값을 저장하는 옵션이 없습니다

이 시도. 여기에 솔루션입니다, 감사에 everbody :

당신은 같은 것을 할 수 있습니다

UPDATE master m 
    INNER JOIN childs c ON m.master_id = c.master_id 
SET master.quantity1 = c.quantity1, 
    master.count = 1 
,

한 번에 하나의 하위 레코드 만있는 경우. 그러나 작동하지 않는 조인 된 테이블에서 SUM() 같은 그룹 함수를 사용하려는 경우. 당신이 일부 또는 "그룹화"를두면 어느 당신은 "그룹 함수의 잘못된 사용을"얻을 GROUP

-- This doesnt work :(
UPDATE master m 
    INNER JOIN childs c ON m.master_id = c.master_id 
SET master.quantity1 = SUM(c.quantity1), 
    master.count = COUNT(c.*) 
GROUP by c.master_id 

솔루션 "c.master_id에 의해"당신이 사용하는 경우 당신은 당신의 SQL 구문에 오류가 있습니다 " 하위 쿼리와 조인을 사용하는 것입니다

UPDATE master m 
    INNER JOIN 
    (
    SELECT master_id, 
      SUM(quantity1) as quantity1, 
      COUNT(*) as count 
    FROM  childs c 
    GROUP BY master_id 
) c 
    ON c.master_id = m.master_id 
SET m.quantity1 = c.quantity1, 
    m.count = c.count 
WHERE m.master_id = 666; 

그러나 이것은 childtable에서 모든 행을 끌어 때문에 오버 헤드 가능성이 원래 SQL처럼 더 하위 쿼리를 사용하는 것보다 더 큰 것 당신이 가입에 WHERE 절을 추가해야합니다 그래서. 표를 사용하여 필요한 행만 가져옵니다.

이 구문은 WHERE 절을 사용하여 JOIN과 동일한 작업을 수행하지만 하위 쿼리의 결과가 추가되므로 동일한 값으로 모든 행을 업데이트하려는 경우 하위 쿼리 만 한 행만 반환하는 경우에만 사용해야합니다. 결과 및 모든 열처럼 사용할 수 있습니다.

UPDATE master m, 
    (
     SELECT SUM(c.quantity1) as sum_of_quantity, 
     COUNT(*) as rowcount FROM child c WHERE c.master_id = 666 
    ) as c 
SET m.quantity1 = c.sum_of_quantity, 
    m.count = c.rowcount 
WHERE m.master_id = 666; 
+0

당신은 업데이트 전에 카운트를하고 노력하고 갱신에 전달하는 것이 라니 변수를 저장할 수있다? –

+0

어떤 오류가 있습니까? 업데이트가 정확합니다. – ksogor

+0

아래에서 작동해야하는 몇 가지 답변이 있지만 반복되는 열과 복제 된 데이터 사이의 매우 비정규적인 디자인처럼 보일뿐입니다. –

답변

2

는 MySQL로 리벤의 솔루션을 다시 쓰기 :

UPDATE master m 
JOIN (
    SELECT master_id 
      , SUM(quantity1) as quantity1 
      , SUM(quantity2) as quantity2 
      , COUNT(*) as count 
    FROM childs c 
    GROUP BY 
      master_id 
) c 
ON c.master_id = m.master_id 
SET 
    m.quantity1 = c.quantity1 
    ,m.quantity2 = c.quantity2 
    ,m.count = c.count 
WHERE m.master_id = 666; 
+0

매력처럼 작동하지만 (내 질문에 업데이 트를 보면) 하위 쿼리에 where 절을 추가하는 것을 잊지 마라. 그렇지 않으면 하나의 레코드를 결합하기 위해 DB에서 수백만 행을 가져올 것이다. –

1

MySQL에서는 허용되는지 모르겠지만 SQL Server에서는 업데이트에서 select 결과를 사용할 수 있습니다.

UPDATE master m SET 
    quantity1 = c.quantity1 
    , quantity2 = c.quantity2 
    , count = c.count 
FROM master m 
     INNER JOIN (
     SELECT master_id 
       , quantity1 = SUM(quantity1) 
       , quantity2 = SUM(quantity2) 
       , count = COUNT(*) 
     FROM childs c 
     WHERE master_id = 666 
     GROUP BY 
       master_id 
    ) c ON c.master_id = m.master_id 
+0

+1, 그게 정확히 어떻게 할 수 –

+0

내 대답에서 MySQL에 대한 올바른 구문을 복사/붙여 넣으면 그 중 하나를 삭제합니다. – Wrikken

+0

@Wrikken, 이것이 MySQL에서 작동하지 않는다고 확신하는 경우 반드시 OP가 답변을 받아 들여야합니다. –

0

데이터를 임시 테이블로 선택한 다음 해당 데이터를 사용하여 업데이트 할 수 있습니다.

당신은 또한 ... INSERT INTO로 보면, 같은 왕복에 "새로운"데이터를 삽입 DUPLICATE KEY UPDATE부터 ... 선택합니다

...

하면 이미 삽입하는 경우를 수행하는 경우 행 존재하지 않는다면,이 예와 중복 될 것입니다.

예 :

INSERT INTO master m (id, quantity1, quantity2, count) 
SELECT master_id, SUM(quantity1) q1, SUM(quantity2) q1, COUNT(*) c 
    FROM childs 
    GROUP BY master_id 
ON DUPLICATE KEY UPDATE 
    m.quantity1 = q1, 
    m.quantity2 = q2, 
    m.count = c 

참고! 이것은 테스트되지 않은 코드이지만 UPDATE에서 선택 결과를 역 참조 할 수 있어야한다고 생각합니다.

구문 참조

: http://dev.mysql.com/doc/refman/5.0/en/insert.html

관련 문제