Chuyển đổi giá trị trong một cột bằng một câu lệnh cập nhật


12

Bạn thấy rằng một lỗi trong một hệ thống đã đặt tên nam (M) không chính xác là nữ (W) và ngược lại trong cơ sở dữ liệu. Các cột chỉ cho phép một ký tự. Không sử dụng bất kỳ bảng tạm thời nào, hãy viết một truy vấn cập nhật để giải quyết vấn đề này.

Câu hỏi này đã được hỏi tại một cuộc phỏng vấn gần đây mà tôi có, và tôi sẽ tham gia nhiều cuộc phỏng vấn hơn có thể có những câu hỏi tương tự vì vậy tôi muốn có một ý tưởng về cách xử lý vấn đề này.


6
Bạn đã được yêu cầu giả định một sản phẩm cơ sở dữ liệu cụ thể? ví dụ: MySQL, SQL Server, Oracle, PostgreSQL ...?
Paul White 9

Hệ thống của bạn đã đọc các hướng dẫn cộng đồng mới chưa? : \
AER

Câu trả lời:


22

Bạn muốn sử dụng một CASEbiểu thức của một số loại.

Trong SQL Server, mã sẽ như thế này:

UPDATE TableName
SET gender = CASE WHEN gender = 'M' THEN 'W' 
                  WHEN gender = 'W' THEN 'M'
                  ELSE gender END

Chỉnh sửa: Như đã nêu trong các nhận xét (và một số câu trả lời khác), ELSE không cần thiết nếu bạn đặt mệnh đề WHERE trên câu lệnh.

UPDATE TableName
SET gender = CASE WHEN gender = 'M' THEN 'W' 
                  WHEN gender = 'W' THEN 'M' END
WHERE gender IN ('M','W')

Điều này tránh những cập nhật không cần thiết. Điều quan trọng trong cả hai trường hợp là hãy nhớ rằng có các tùy chọn khác ngoài M & W (ví dụ NULL) và bạn không muốn đưa thông tin sai. Ví dụ:

UPDATE TableName
SET gender = CASE WHEN gender = 'M' THEN 'W' 
                  ELSE 'M' END

Điều này sẽ thay thế bất kỳ NULL nào (hoặc các giới tính có thể khác) thành 'M' sẽ không chính xác.


Một vài lựa chọn khác sẽ là

/*Simple form of CASE rather than Searched form*/
UPDATE TableName
SET    gender = CASE gender
                  WHEN 'M' THEN 'W'
                  WHEN 'W' THEN 'M'
                END
WHERE  gender IN ( 'M', 'W' );

Và ngắn gọn hơn

/*For SQL Server 2012+*/
UPDATE TableName
SET    gender = IIF(gender = 'M', 'W', 'M')
WHERE  gender IN ( 'M', 'W' ); 

1
Bạn có thể thay thế IIF()bằng IF()và nó sẽ hoạt động trong MySQL;)
ypercubeᵀᴹ

9

Trong Oracle, bạn có thể sử dụng CASE như các câu trả lời khác có:

UPDATE TableName
SET gender = CASE WHEN gender = 'M' THEN 'W' 
                  WHEN gender = 'W' THEN 'M'
             END
WHERE gender in ('M','W');

Bạn cũng có thể sử dụng một DECODE:

UPDATE TableName SET gender = DECODE(gender,'M','W','W','M')
WHERE gender in ('M','W');

5

Để chuyển đổi giữa hai giá trị, bạn cũng có thể thử mẹo này, không sử dụng CASEbiểu thức (giả sử Transact-SQL ở đây):

UPDATE
  YourTable
SET
  Gender = CHAR(ASCII('M') + ASCII('W') - ASCII(Gender))
WHERE
  Gender IN ('M', 'W')
;

Tùy thuộc vào giá trị hiện tại của Gender, ASCII(Gender)sẽ hủy bỏASCII('M') hoặc ASCII('W')để lại mã khác được chuyển đổi bởi CHAR()hàm trở lại ký tự tương ứng.

Tôi đang để điều này chỉ để so sánh, mặc dù. Mặc dù tùy chọn này có thể giả vờ thanh lịch, nhưng một giải pháp sử dụng CASEbiểu thức có thể dễ đọc hơn và do đó dễ bảo trì hơn và chắc chắn sẽ dễ dàng mở rộng hơn hai giá trị.


2
Chúng ta hãy hy vọng tất cả MWđược nhập vào chữ hoa để tránh bất ngờ 7hoặc `-` xuất hiện trong kết quả.
Martin Smith

@MartinSmith: Điểm rất tốt. Nếu chúng không được, chúng tôi sẽ phải thay thế ASCII(Gender)với ASCII(UPPER(Gender)), đó là ít thanh lịch, mặc dù không nhiều.
Andriy M

@MartinSmith nếu có chữ thường là m và w, họ sẽ không bị từ chối bởi WHEREđiều khoản chứ?
ypercubeᵀᴹ

1
@ YperSillyCubeᵀᴹ - Chỉ trong trường hợp va chạm nhạy cảm (không phải IME thông thường)
Martin Smith

4

Bạn có thể làm điều đó với một case ... whenbiểu thức:

mysql> select * from genderswap;
+--------+
| gender |
+--------+
| F      |
| F      |
| M      |
| M      |
| M      |
| M      |
| M      |
+--------+
7 rows in set (0.00 sec)

mysql> 
mysql> UPDATE genderswap SET gender = case 
    ->                                when gender='M' then 'F' 
    ->                                when gender='F' then 'M'
    ->                                end
    -> WHERE gender IN ('M', 'F');
Query OK, 7 rows affected (0.00 sec)
Rows matched: 7  Changed: 7  Warnings: 0

mysql> 
mysql> select * from genderswap;
+--------+
| gender |
+--------+
| M      |
| M      |
| F      |
| F      |
| F      |
| F      |
| F      |
+--------+
7 rows in set (0.00 sec)

mysql> 

2

Tôi sẽ sử dụng một bản cập nhật với một casebiểu thức.

DECLARE @Test TABLE
    (
      Name VARCHAR(100) NULL
    , Gender CHAR(1) NULL
    );

INSERT  INTO @Test
        ( Name, Gender )
VALUES  ( 'Jonathan', 'W' )
         ,
        ( 'Kelly', 'M' );

SELECT  Name
      , Gender
FROM    @Test;

UPDATE  @Test
SET     Gender = CASE WHEN Gender = 'M' THEN 'W'
                      ELSE 'M'
                 END;

SELECT  Name
      , Gender
FROM    @Test;

-1

Bạn có thể thực hiện cập nhật này bằng cách sử dụng một casebiểu thức.

UPDATE names_table
   SET names_table.gender = ( CASE
                                  WHEN names_table.gender = 'M'
                                    THEN 'W'
                                  ELSE
                                      names_table.gender = 'M'
                              END)

Tôi khuyên bạn nên chạy câu lệnh cập nhật của mình trong một giao dịch và thêm một truy vấn đơn giản, chẳng hạn như:

SELECT n.gender, *
FROM names_table

để kiểm tra kết quả bạn sẽ nhận được. Thực hiện giao dịch với một rollback và chuyển nó thành một cam kết khi kết quả của bạn phù hợp với những gì bạn mong đợi.

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.