Beralih nilai dalam kolom dengan satu pernyataan pembaruan

12

Anda menemukan bahwa kesalahan dalam suatu sistem telah salah menyebut pria (M) sebagai wanita (W) dan sebaliknya dalam database. Kolom hanya memungkinkan untuk satu karakter. Tanpa menggunakan tabel temp, tulis satu permintaan pembaruan untuk menyelesaikan ini.

Pertanyaan ini diajukan pada wawancara baru-baru ini yang saya lakukan, dan saya akan melakukan lebih banyak wawancara yang mungkin memiliki pertanyaan serupa sehingga saya ingin mendapatkan ide tentang bagaimana menangani hal ini.

SethYes
sumber
6
Apakah Anda diminta untuk menggunakan produk basis data tertentu? misal MySQL, SQL Server, Oracle, PostgreSQL ...?
Paul White 9
Apakah sistem Anda membaca pedoman komunitas baru? : \
AER

Jawaban:

22

Anda ingin menggunakan CASEekspresi dari beberapa tipe.

Dalam SQL Server kode akan terlihat seperti ini:

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

Sunting: Sebagaimana dinyatakan dalam komentar (dan beberapa jawaban lainnya) ELSE tidak perlu jika Anda menempatkan klausa WHERE pada pernyataan.

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

Ini menghindari pembaruan yang tidak perlu. Yang penting dalam kedua kasus ini adalah untuk mengingat bahwa ada opsi selain M&W (NULL misalnya) dan Anda tidak ingin memasukkan informasi yang salah. Sebagai contoh:

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

Ini akan menggantikan NULL (atau jenis kelamin lain yang mungkin) sebagai 'M' yang tidak benar.


Beberapa opsi lain bisa jadi

/*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' );

Dan yang lebih ringkas

/*For SQL Server 2012+*/
UPDATE TableName
SET    gender = IIF(gender = 'M', 'W', 'M')
WHERE  gender IN ( 'M', 'W' ); 
Kenneth Fisher
sumber
1
Anda dapat mengganti IIF()dengan IF()dan itu akan bekerja di MySQL;)
ypercubeᵀᴹ
9

Di Oracle Anda bisa menggunakan KASUS seperti jawaban lain:

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

Anda juga dapat menggunakan DECODE:

UPDATE TableName SET gender = DECODE(gender,'M','W','W','M')
WHERE gender in ('M','W');
Leigh Riffel
sumber
5

Untuk beralih di antara hanya dua nilai, Anda juga bisa mencoba trik ini, yang tidak menggunakan CASEekspresi (dengan asumsi Transact-SQL di sini):

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

Bergantung pada nilai saat ini Gender, ASCII(Gender)akan membatalkan salah satu ASCII('M')atau ASCII('W'), meninggalkan kode lain untuk diubah oleh CHAR()fungsi kembali ke karakter yang sesuai.

Saya meninggalkan ini hanya untuk perbandingan. Meskipun opsi ini mungkin berpura-pura anggun, sebuah solusi yang menggunakan CASEungkapan bisa dibilang lebih mudah dibaca dan dengan demikian lebih mudah dipertahankan, dan tentu saja akan lebih mudah diperluas ke lebih dari dua nilai.

Andriy M
sumber
2
Mari berharap semua Mdan Wdimasukkan dalam huruf besar untuk menghindari yang tak terduga 7atau `-` muncul dalam hasil.
Martin Smith
@ MartinSmith: Poin yang sangat bagus. Jika tidak, kita harus menggantinya ASCII(Gender)dengan ASCII(UPPER(Gender)), yang kurang elegan, meskipun tidak banyak.
Andriy M
@ MartinSmith jika ada huruf kecil m dan w, bukankah mereka akan ditolak oleh WHEREklausa?
ypercubeᵀᴹ
1
@ YperSillyCubeᵀᴹ - Hanya dalam pemeriksaan case sensitif (yang bukan IME biasa)
Martin Smith
4

Anda dapat melakukannya dengan case ... whenekspresi:

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> 
Philᵀᴹ
sumber
2

Saya akan menggunakan pembaruan dengan caseekspresi.

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;
Jonathan Fite
sumber
-1

Anda dapat melakukan pembaruan ini menggunakan caseekspresi.

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

Saya sarankan menjalankan pernyataan pembaruan Anda dalam transaksi dan menambahkan kueri sederhana seperti:

SELECT n.gender, *
FROM names_table

untuk memeriksa hasil yang akan Anda dapatkan. Melakukan transaksi dengan rollback dan mengubahnya menjadi komitmen ketika hasil Anda sesuai dengan yang Anda harapkan.

agpoweredmg
sumber