1つの更新ステートメントで列の値を切り替える


12

システムのエラーにより、データベースで男性(M)を女性(W)に、またはその逆に誤って命名していることがわかりました。列には1文字しか入力できません。一時テーブルを使用せずに、これを解決する更新クエリを1つ記述します。

この質問は、最近行ったインタビューで尋ねられました。同様の質問がある可能性があるインタビューをさらに調査するため、これをどのように処理するかについてのアイデアを得たいと思いました。


6
特定のデータベース製品を想定するように求められましたか?例:MySQL、SQL Server、Oracle、PostgreSQL ...?
ポールホワイト9

システムは新しいコミュニティガイドラインを読みましたか?:\
AER

回答:


22

CASEあるタイプの式を使用したい。

SQL Serverでは、コードは次のようになります。

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

編集: コメント(および他のいくつかの回答)に記載されているように、ステートメントにWHERE句を指定する場合、ELSEは必要ありません。

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

これにより、不要な更新を回避できます。どちらの場合でも重要なことは、MとW以外のオプション(たとえば、NULL)があり、誤った情報を入力したくないということを覚えておくことです。例えば:

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

これは、NULL(または他の可能な性別)を「M」として置き換えますが、これは正しくありません。


他のいくつかのオプションは

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

そしてより簡潔な

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

1
あなたは置き換えることができIIF()IF()、それは、MySQLで動作します。)
ypercubeᵀᴹ

9

Oracleでは、他の答えがあるようにCASEを使用できます:

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

DECODEを使用することもできます。

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

5

2つの値だけを切り替えるには、CASE式を使用しないこのトリックを試すこともできます(ここではTransact-SQLを想定しています)。

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

現在の値に応じてGenderASCII(Gender)いずれかの相殺になるASCII('M')ASCII('W')によって変換する他のコードを残して、CHAR()対応する文字への関数バック。

ただし、比較のために残しておきます。このオプションはそれを優雅に見せかけているかもしれCASEませんが、式を使用するソリューションは間違いなく読みやすく、保守が容易であり、3つ以上の値に展開する方が間違いなく簡単です。


2
予期しない結果や「-」が結果に表示されないように、MWがすべて大文字で入力されていることを願っ7ています。
Martin Smith、

@MartinSmith:非常に良い点です。彼らがいなかった場合、我々は交換する必要がありますASCII(Gender)ASCII(UPPER(Gender))あまりしていないが、あまりエレガントです。
Andriy M

@MartinSmith小文字のmとwがある場合、それらはWHERE句によって拒否されませんか?
ypercubeᵀᴹ

1
@YperSillyCubeᵀᴹ-大文字と小文字を区別する照合(通常のIMEではない)の場合のみ
Martin Smith

4

あなたはcase ... when式でそれを行うことができます:

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

case式で更新を使用します。

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

case式を使用してこの更新を実行できます。

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

トランザクション内で更新ステートメントを実行し、次のような簡単なクエリを追加することをお勧めします。

SELECT n.gender, *
FROM names_table

あなたが得る結果を確認するために。結果が期待どおりになったら、トランザクションをロールバックで実行し、コミットに切り替えます。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.