2013-08-06 24 views
5

güncelleme kendiliğinden tablosu: verilerinin altındaki ilenasıl Mysql MySQL bir tablo var iş

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

:

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

Şimdi veri olmalıdır:

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

İstiyorum sütun b'yi min (b) grubuna sütun a'ya göre güncelleştirin.

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

Ama MYSQL SQL iyi performansla sorumu çözebilir aşağıda düşünüyorum

Yani FROM yan tümcesinde güncelleştirme için hedef tablo belirtilemiyor:

Yani SQL olmalıdır

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; 

Ama sonucudur:

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

Aslında ihtiyacım sonucudur:

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

Soru 1: Neden MYSQL SQL ile yanlış sonuç çalışmak? İyi verimli doğru SQL ne olmalı?
Soru 2: Sadece NULL değeriyle güncellemek istediğimde SQL'in ne olması gerekir (sadece üçüncü kaydı güncelleştirin)?

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; 

cevap

4

Satırlarınızı tanımlamak için benzersiz bir sütununuz yok. Yani, JOIN, muhtemelen düşündüğünüz şekilde daha fazla satırı güncelleyecektir.


Muhtemelen bunun yerine böyle bir şey istiyorum: Sadece sütunda b yılında NULL sahip satırları güncellemek istiyorsanız

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


Bakın, bu sadece WHERE numaralı yazgı:

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

Bu sizin SQL kullanarak 4.5 milyon kayıtları ile tek tabloda güncellemek için yaklaşık 5 dakika sürer. SQL'imin hatasını öğrenmeme yardım edebilir misin? – bluearrow

+0

@bluearrow Bu farklı bir konu olduğundan, tablonuzun yapısını (dizininiz dahil), isteğinizi ve [sorgu planını] (http://dev.mysql.com/doc/refman) sağlayarak başka bir soru sormalısınız. /4.1/en/execution-plan-information.html). –

+0

Cevabınızı bekliyoruz: http://stackoverflow.com/questions/18117717/mysql-join-update-internal-steps – bluearrow

0

Bunu yapmak için geçici bir tablo kullanabilirsiniz: Söz 2 Hakkında

, aşağıda yanlış SQL kullanmaya çalıştık

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; 

Bunu çalışması gerektiğini düşünüyorum. Bağlantı formu kapatıldığında, tem1, her ne kadar iyi bir form olsa da, yine de bırakılacağından, 'bırakma tablosu' kesinlikle gerekli değildir.

0

Write it as a JOIN instead bakınız:

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

Bu iyi bir yöntemdir. Ama bence masadaki endeks yok. SQL'imin hatasını öğrenmeme yardım edebilir misin? – bluearrow