2013-08-06 84 views
5

Tôi có một bảng trong MYSQL:cách mysql cập nhật tự bàn làm việc

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

Với dưới đây dữ liệu:

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

Bây giờ dữ liệu nên là:

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

Tôi muốn cập nhật cột b vào nhóm min (b) theo cột a.

Vì vậy, SQL nên là:

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

Nhưng MYSQL Không thể chỉ định bảng mục tiêu cho bản cập nhật trong mệnh đề FROM

Vì vậy, tôi nghĩ rằng bên dưới SQL có thể giải quyết câu hỏi của tôi với hiệu suất tốt:

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; 

Nhưng kết quả là:

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

Trên thực tế kết quả tôi cần là:

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

Câu hỏi 1: Tại sao MYSQL làm việc ra các kết quả không chính xác với SQL? SQL đúng với hiệu quả tốt nên là gì?
Câu hỏi 2: SQL nên là gì nếu tôi chỉ muốn cập nhật b với giá trị NULL (chỉ cập nhật bản ghi thứ ba)?

thiệu về câu hỏi 2, tôi đã cố gắng sử dụng SQL không chính xác dưới đây:

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; 

Trả lời

4

Bạn không có cột duy nhất để xác định các hàng của mình. Vì vậy, JOIN của bạn có thể sẽ cập nhật nhiều hàng hơn như bạn nghĩ.


Bạn có thể muốn một cái gì đó như thế thay vì:

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; 

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


Nếu bạn chỉ muốn cập nhật các hàng có NULL trong cột b, đây chỉ là một vấn đề của mệnh đề 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; 

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

+0

Phải mất khoảng 5 phút để cập nhật trong một bảng với 4,5 triệu bản sử dụng SQL của bạn. Bạn có thể giúp tôi tìm ra lỗi của SQL của tôi không? – bluearrow

+0

@bluearrow Vì đây là một chủ đề khác, bạn nên hỏi một câu hỏi khác, cung cấp cấu trúc bảng (bao gồm chỉ mục của bạn), yêu cầu và [kế hoạch truy vấn] của nó (http://dev.mysql.com/doc/refman /4.1/en/execution-plan-information.html). –

+0

Rất mong nhận được câu trả lời của bạn: http://stackoverflow.com/questions/18117717/mysql-join-update-internal-steps – bluearrow

0

Bạn có thể sử dụng một bảng tạm thời để làm điều này:

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; 

Tôi nghĩ rằng nên làm việc. Các 'thả bảng' là không cần thiết nghiêm trọng vì tem2 sẽ được giảm anyway khi kết nối được đóng lại, mặc dù nó là hình thức tốt.

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

Đó là một phương pháp hay. Nhưng tôi nghĩ bàn phút không có chỉ mục. Bạn có thể giúp tôi tìm ra lỗi của SQL của tôi không? – bluearrow