2013-08-06 7 views
5

업데이트 자체 테이블 : 데이터를 아래로어떻게 MySQL은 내가 MYSQL의 테이블이 작업

CREATE TABLE test.tem(a INT,b INT);  

을 :

INSERT INTO test.tem VALUES(1,2),(1,1),(1,NULL),(2,3); 

이제 데이터가 있어야한다 :

+------+------+ 
| a | b | 
+------+------+ 
| 1 | 2 | 
| 1 | 1 | 
| 1 | NULL | 
| 2 | 3 | 
+------+------+ 

내가 원하는 b 열을 a 열로 min (b) 그룹으로 업데이트하십시오.

UPDATE test.tem o 
SET o.b = (SELECT 
      MIN(b) 
      FROM test.tem i 
      WHERE i.a = o.a) 

그러나 MYSQL 내가 SQL 좋은 성능을 내 질문을 해결할 수 아래로 생각

그래서 FROM 절에 업데이트를 목표 테이블을 지정할 수 없습니다 :

는 그래서 SQL은해야

UPDATE test.tem t1 
    JOIN test.tem t2 
    ON t1.a = t2.a 
SET t1.b = t2.b 
WHERE t1.b IS NULL 
    OR t1.b > t2.b; 

그러나 결과는 다음과 같습니다

+------+------+ 
| a | b | 
+------+------+ 
| 1 | 1 | 
| 1 | 1 | 
| 1 | 2 | 
| 2 | 3 | 
+------+------+ 

사실 내가 원하는 결과는 다음과 같습니다

+------+------+ 
| a | b | 
+------+------+ 
| 1 | 1 | 
| 1 | 1 | 
| 1 | 1 | 
| 2 | 3 | 
+------+------+ 

질문 1 : 왜 MYSQL은 SQL과 잘못된 결과를 해결? 효율적인 SQL을 사용하는 올바른 SQL은 무엇이되어야합니까?
질문 2 : b 만 NULL 값으로 업데이트하려는 경우 SQL이 있어야합니다 (세 번째 레코드 만 업데이트)?

UPDATE test.tem t1 
    JOIN test.tem t2 
    ON t1.a = t2.a 
    AND t1.b IS NULL 
SET t1.b = t2.b 
WHERE t1.b IS NULL 
    OR t1.b > t2.b; 

답변

4

행을 식별하는 고유 한 열이 없습니다. 따라서 JOIN은 생각보다 많은 행을 업데이트합니다.


당신은 아마 대신 같은 것을 원하는 : 당신은 단지 열 BNULL을 갖는 행을 업데이트하려면

UPDATE tem AS t1 JOIN (SELECT a, MIN(b) AS m FROM tem GROUP BY a) AS t2 
USING (a) 
SET t1.b = t2.m; 

http://sqlfiddle.com/#!2/c6a04/1


참조, 이것은 단지입니다 WHERE 조항 :

CREATE TABLE tem(a INT,b INT);  
INSERT INTO tem VALUES(1,2),(1,1),(1,NULL),(2,3); 

UPDATE tem AS t1 JOIN (SELECT a, MIN(b) AS m FROM tem GROUP BY a) AS t2 
USING (a) 
SET t1.b = t2.m 
WHERE t1.b IS NULL; 

http://sqlfiddle.com/#!2/31ffb/1

+0

그것은 당신의 SQL을 사용하여 450 만 개 기록을 하나 개의 테이블에 업데이트하는 약 5 분 정도 소요됩니다. SQL의 오류를 찾아 내도록 도와 줄 수 있습니까? – bluearrow

+0

@bluearrow 다른 주제이므로 테이블 구조 (색인 포함), 요청 및 쿼리 계획 (http://dev.mysql.com/doc/refman)을 제공하여 다른 질문을해야합니다. /4.1/en/execution-plan-information.html). –

+0

답을 찾으십시오 : http://stackoverflow.com/questions/18117717/mysql-join-update-internal-steps – bluearrow

0

당신은이 작업을 수행하기 위해 임시 테이블을 사용할 수 있습니다 : 질문 2에 대해

는, 나는 아래의 잘못된 SQL을 사용하는 것을 시도했다

create temporary table tem2 (a INT, b INT); 

insert into tem2 
    select a, min(b) from tem group by a; 

update tem 
    inner join tem2 on tem.a = tem2.a 
    set tem.b = tem2.b; 

drop table tem2; 

내가 그 일을한다고 생각합니다. '드롭 테이블'은 꼭 필요한 것은 아니지만 연결이 닫힐 때 tem2가 삭제되므로 절대적으로 필요하지 않습니다.

0

Write it as a JOIN instead를 참조하십시오

UPDATE tem 
JOIN (SELECT a, MIN(b) AS min_b FROM tem GROUP BY a) AS mins USING (a) 
SET tem.b = mins.min_b ; 
+0

그게 좋은 방법입니다. 하지만 분 테이블에는 색인이 없다고 생각합니다. SQL의 오류를 찾아 내도록 도와 줄 수 있습니까? – bluearrow

관련 문제