2009-05-27 51 views
11

Về cơ bản tôi cần phải làm một cái gì đó như thế này .... đây chỉ là một ví dụ ... nhưng cú pháp của truy vấn đầu tiên không làm việc trong MySQLmysql lồng SELECT trong CẬP NHẬT của cùng một bảng

update people set prize = '' 
where prize = 'Gold' and class = (select class from people where id = person_id); 
update people set prize = 'Gold' where id = <id>; 

Chỉ một người có thể có giải Vàng ở bất kỳ hạng nào. Tôi chỉ biết person_id của người nhận giải Vàng.

Tôi đang cố gắng xóa mọi người giành giải thưởng Vàng trước đó trong cùng một lớp với person_id trong truy vấn đầu tiên. Sau đó thiết lập người chiến thắng Vàng mới trong lần thứ hai.

Tôi tin rằng tôi cần phải sử dụng một số loại tham gia bên trong, nhưng tôi không chắc chắn 100% về điều này.

Điều gì sẽ càng thông minh hơn nếu tôi có thể thực hiện toàn bộ rất nhiều trong một truy vấn!

Mọi người có thể cho vay lời khuyên không?

Cảm ơn :)

Trả lời

7
UPDATE people 
SET prize = CASE WHEN id = @lucky THEN 'Gold' ELSE 'Silver' END 
WHERE class = (
     SELECT class 
     FROM people 
     WHERE id = @lucky 
     ) 

này sẽ cấp tất cả người dùng với một giải thưởng Silver, ngoại trừ @lucky một trong những người nhận được Gold.

Nếu bạn chỉ cần cập nhật @lucky và cựu vô địch, phát hành như sau:

UPDATE people 
SET prize = CASE WHEN id = @lucky THEN 'Gold' ELSE 'Silver' END 
WHERE id = @lucky 
     OR (class, prize) = 
     (
     SELECT class, 'Gold' 
     FROM people 
     WHERE id = @lucky 
     ) 
+0

này không làm tương tự như đăng trong câu hỏi. Bạn đang ghi đè mọi giải thưởng trong một lớp học với "Vàng" hoặc "Bạc" trong khi truy vấn trên chỉ xóa các giải thưởng "Vàng" và đặt giải thưởng mới. Ví dụ: nếu một trong những người có giá "Đồng" thì sao? – VVS

+0

@David Hympohl: Tốt, bạn có thể làm điều đó bằng cách thêm "WHERE class = 'Gold" hoặc id = @lucky "vào cuối truy vấn. – Andomar

+0

@David: truy vấn của @ op đặt giải thưởng thành '' cho mỗi người trong lớp. Tôi chỉ cần thay thế '' bằng 'Bạc' để dễ đọc – Quassnoi

0

Bạn chắc chắn có thể tạo ra một stored procedure mà sẽ đưa id của người chiến thắng giải thưởng mới như một cuộc tranh cãi.

Sau đó, bạn có thể gọi thủ tục được lưu trữ đó trong một dòng.

Tôi đang sử dụng MS SQL ở đây nhưng một cái gì đó tương tự như:

CREATE PROC UpdatePrize 
    @newid int 

AS 

UPDATE people 
SET prize = '' 
WHERE prize = 'Gold' 
AND class = (SELECT class 
       FROM people 
       WHERE id = @newid) 

UPDATE people 
SET prize = 'Gold' 
WHERE id = @newid 

GO 
1

Nếu bạn đang theo đuổi một tuyên bố duy nhất bạn có thể sử dụng toán tử TRƯỜNG HỢP? Không được sử dụng MySQL nhưng giống như:

UPDATE people 
SET prize = CASE 
       WHEN 'Gold' AND id != @newid THEN '' 
       WHEN '' AND id = @newid THEN 'Gold' 
      END 
WHERE class = ( 
       SELECT class 
       FROM people 
       WHERE id = @newid 
      ) 
+0

Trường hợp nào là 'KHI NÀO' phải làm gì? Luôn trả về false trên máy chủ của tôi. :) – Andomar

+0

ah xin lỗi, đã không kiểm tra nó. Bạn có thể sử dụng giải thưởng CASE WHEN 'Gold' THEN .... hoặc nếu bạn cần sử dụng biểu thức CASE WHEN award = 'Gold' THEN ... WHEN award = '' THEN .... –

0

Vì bạn đang thực hiện hai cập nhật riêng biệt nên không cần thực hiện trong một truy vấn. Nếu bạn sợ dữ liệu không nhất quán vì một trong hai truy vấn có thể không thành công, bạn có thể sử dụng các giao dịch và rollback của bất kỳ truy vấn nào không thành công.

Truy vấn hiện tại của bạn hoàn toàn có thể đọc được và dễ hiểu trong khi các giải pháp đã đăng không dễ đọc.

10

Không phải lúc nào cũng tốt nhất để thực hiện các cập nhật phức tạp trong một truy vấn SQL đơn lẻ. Trong thực tế, nó có thể hiệu quả hơn để chạy hai truy vấn đơn giản. Vì vậy, hãy chắc chắn để chuẩn cho cả hai giải pháp.

MySQL hỗ trợ phần mở rộng cho cú pháp UPDATE để cập nhật nhiều bảng. Bạn có thể thực hiện một JOIN như một phần của bản cập nhật thay vì sử dụng các truy vấn phụ.

Sau đó, bạn có thể sử dụng chức năng IF() (hoặc CASE) để thay đổi giá trị prize thành các giá trị khác nhau có điều kiện.

Vì vậy, nếu bạn hoàn toàn phải sử dụng một truy vấn duy nhất, hãy thử một cái gì đó như thế này:

UPDATE people p1 JOIN people p2 
    ON (p1.class = p2.class AND p2.id = <person_id>) 
SET prize = IF(p1.id = <person_id>, 'Gold', '') 
WHERE p1.id = <person_id> OR p1.prize = 'Gold'; 

Hoặc thay thế này:

UPDATE people p1 JOIN people p2 
    ON (p1.class = p2.class AND p2.id = <person_id>) 
SET p1.prize = CASE 
    WHEN p1.id = <person_id> THEN 'Gold' 
    WHEN p1.prize = 'Gold' THEN '' 
    ELSE p1.prize -- other cases are left as is 
END CASE; 
+0

Sẽ không đồng này cướp chủ sở hữu giải thưởng của huy chương của họ? – Andomar

+0

@Andomar: Bạn nói đúng. Tôi đã chỉnh sửa câu trả lời với điều này trong tâm trí. –

Các vấn đề liên quan