Làm cách nào để cập nhật một bảng dựa trên các giá trị của bảng khác một cách nhanh chóng?


40

Tôi có một bảng trong tên của ips như sau:

CREATE TABLE `ips` (
 `id` int(10) unsigned NOT NULL DEFAULT '0',
 `begin_ip_num` int(11) unsigned DEFAULT NULL,
 `end_ip_num` int(11) unsigned DEFAULT NULL,
 `iso` varchar(3) DEFAULT NULL,
 `country` varchar(150) DEFAULT NULL
) ENGINE=InnoDB

Giả sử tôi có một countryidtrường trên bảng này từ bảng quốc gia như sau:

CREATE TABLE `country` (
 `countryid` tinyint(3) unsigned NOT NULL AUTO_INCREMENT,
 `name` varchar(50) CHARACTER SET utf8 COLLATE utf8_unicode_ci NOT NULL,
 `ordering` smallint(5) unsigned NOT NULL DEFAULT '0',
 `iso` char(2) NOT NULL,
 PRIMARY KEY (`countryid`)
) ENGINE=InnoDB

Có khoảng 100.000 hồ sơ trong bảng ips. Có bất kỳ truy vấn nào cho kịch bản sau đây không:
Kiểm tra xem ips.isocó bằng không country.iso, nếu nó bằng nhau thì thêm country.coutryid vào bản ghi đó. Tôi không thể nghĩ ra cách nào để làm điều đó. Bạn có bất cứ ý tưởng làm thế nào để làm điều đó?

Câu trả lời:


72
UPDATE ips INNER JOIN country
    ON ips.iso = country.iso
SET ips.countryid = country.countryid

Sử dụng MySQL cập nhật cú pháp nhiều bảng:

14.2.11 Cú pháp CẬP NHẬT

Lưu ý rằng bạn có hai độ dài và loại dữ liệu khác nhau trên các cột iso của bạn. Trên thực tế, có hai bộ mã ISO riêng biệt, 2 chữ cái và 3 chữ cái, vì vậy trên thực tế bạn có thể không tham gia các cột này:

ISO 3166-1

Các điều kiện tham gia USING (iso)thay vì ON ips.iso = country.isolàm việc quá.


Bạn là một thiên tài mà bạn trả lời đã tiết kiệm thời gian của tôi
humphrey

Điều làm tôi ngạc nhiên là làm thế nào ít mã là cần thiết để thực hiện hành động này!
Matt Cremeens

32

Giải pháp của @Cade Roux mang đến cho tôi một lỗi cú pháp, một lỗi chính xác cho mysql 5.5.29 là:

UPDATE ips 
INNER JOIN country
    ON ips.iso = country.iso
SET ips.countryid = country.countryid

không có từ khóa "TỪ".


1
Nó đã được sửa chữa, dường như ...
rogerdpack

10

Cú pháp này có thể dễ đọc hơn

UPDATE country p, ips pp
SET pp.countryid = p.countryid
WHERE pp.iso = p.iso

4

cảm ơn @Cade, nhưng tôi đã tìm thấy một giải pháp đơn giản cho nó:

update ips set countryid=(select countryid from country where ips.iso=country.iso )

5
Có một sự khác biệt trong hành vi đối với phiên bản của tôi - phiên bản của bạn sẽ đặt nó thành NULL nếu không tìm thấy, phiên bản của tôi sẽ không thay đổi giá trị hiện có nếu không phù hợp. Điều này có thể hoặc không thể được mong muốn. Ngoài ra kế hoạch thực hiện có thể khác nhau tùy thuộc vào trình tối ưu hóa.
Cade Roux

@CadeRoux Tôi không nghĩ về phần NULL, cảm ơn.
ALH

1
@ john.locke Đây có thể không phải là vấn đề - khi bạn thêm cột mới, tôi cho rằng đó sẽ là NULL và cũng là khóa ngoại, vì vậy các mục nhập không hợp lệ sẽ không được phép. Nhưng thật khó để nói từ những gì đã được đưa ra rõ ràng trong câu hỏi của bạn.
Cade Roux
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.