SQL SERVER – A Puzzle – Swap Value of Column Without Case Statement

For the last few weeks, I have been doing Friday Puzzles and I am really loving it. Yesterday I received a very interesting question by Navneet Chaurasia on Facebook Page. He was asked this question in one of the interview questions for job. Please read the original thread for a complete idea of the conversation. I am presenting the same question here.

Puzzle

Let us assume there is a single column in the table called Gender. The challenge is to write a single update statement which will flip or swap the value in the column. For example if the value in the gender column is ‘male’ swap it with ‘female’ and if the value is ‘female’ swap it with ‘male’.

Here is the quick setup script for the puzzle.

USE tempdb
GO
CREATE TABLE SimpleTable (ID INT, Gender VARCHAR(10))
GO
INSERT INTO SimpleTable (ID, Gender)
SELECT 1, 'female'
UNION ALL
SELECT 2, 'male'
UNION ALL
SELECT 3, 'male'
GO
SELECT *
FROM SimpleTable
GO

The above query will return following result set.

SQL SERVER - A Puzzle - Swap Value of Column Without Case Statement genderswap1

The puzzle was to write a single update column which will generate following result set.

SQL SERVER - A Puzzle - Swap Value of Column Without Case Statement genderswap2

There are multiple answers to this simple puzzle. Let me show you three different ways. I am assuming that the column will have either value ‘male’ or ‘female’ only.

Method 1: Using CASE Statement

I believe this is going to be the most popular solution as we are all familiar with CASE Statement.

UPDATE SimpleTable
SET Gender = CASE Gender WHEN 'male' THEN 'female' ELSE 'male' END
GO
SELECT *
FROM SimpleTable
GO

Method 2: Using REPLACE  Function

I totally understand it is the not cleanest solution but it will for sure work in giving situation.

UPDATE SimpleTable
SET Gender = REPLACE(('fe'+Gender),'fefe','')
GO
SELECT *
FROM SimpleTable
GO

Method 3: Using IIF in SQL Server 2012

If you are using SQL Server 2012 you can use IIF and get the same effect as CASE statement.

UPDATE SimpleTable
SET Gender = IIF(Gender = 'male', 'female', 'male')
GO
SELECT *
FROM SimpleTable
GO

You can read my article series on SQL Server 2012 various functions over here.

Let us clean up.

DROP TABLE SimpleTable
GO

Question to you:

I came up with three simple tricks where there is a single UPDATE statement which swaps the values in the column. Do you know any other simple trick? If yes, please post here in the comments. I will pick two random winners from all the valid answers. Winners will get 1) Print Copy of SQL Server Interview Questions and Answers 2) Free Learning Code for Online Video Courses

I will announce the winners on coming Monday.

Reference:  Pinal Dave (https://blog.sqlauthority.com)

Previous Post
SQL SERVER – Tricks to Replace SELECT * with Column Names – SQL in Sixty Seconds #017 – Video
Next Post
SQL SERVER – Service Broker and CAP_CPU_PERCENT – Limiting SQL Server Instances to CPU Usage

Related Posts

No results found.

78 Comments. Leave new

  • Roji P Thomas
    June 8, 2012 7:08 am

    UPDATE S
    SET S.Gender = D.Gender
    FROM SimpleTable S
    INNER JOIN SimpleTable D
    ON S.Gender != D.Gender

    Reply
  • Roji P Thomas
    June 8, 2012 7:11 am

    UPDATE S
    SET S.Gender = (SELECT TOP 1 Gender FROM SimpleTable D WHERE D.Gender != S.Gender)
    FROM SimpleTable S

    Reply
    • Can you please try this string to replace.

      I want to replace a Value from a record like as shown below,

      AASDFADFAGE,CLODFVER to True,True
      ISDRFOQUASA,GREG,FIRIEN to True,True,True
      ADADFDS,ZSERCL1VER to True,True
      DIOFFISFW,AFGREG,GGFRIEN to True,True,True

      With out using XML. Any suggestions please…

      Reply
  • Roji P Thomas
    June 8, 2012 7:31 am

    UPDATE SimpleTable
    SET Gender = RIGHT(‘fe’+Gender, ISNULL(NULLIF(LEN(Gender)+2, 8),4))

    Reply
  • Roji P Thomas
    June 8, 2012 7:55 am

    UPDATE SimpleTable
    SET Gender = STUFF(‘fe’+Gender, 1, CHARINDEX(‘female’, gender)*4, ”)

    Reply
  • Roji P Thomas
    June 8, 2012 8:02 am

    UPDATE SimpleTable
    SET Gender = SUBSTRING(‘fe’+Gender, CHARINDEX(‘female’,Gender)*5, 7)

    –That’s all for the time being :)

    Reply
  • Roji P Thomas
    June 8, 2012 8:10 am

    –OK. Seriously the last one. and a bit elegant :)
    UPDATE SimpleTable
    SET Gender = ISNULL(NULLIF(‘fe’+Gender, ‘fefemale’), ‘male’)

    Reply
  • Inner join……Update Male Set M.Gender=F.Gender from simpleTable Male inner join SimpleTable Female on Male.gender!=Female.gender

    Reply
  • Anil Purswani
    June 8, 2012 9:21 am

    Oh! not as simple as you are expecting…Could be the most complex one :-) ….but I came up with this solution (and yeah! its again includes ‘case statement’)

    SELECT *
    FROM SimpleTable;

    WITH FemaleRows AS(
    SELECT *
    FROM SimpleTable
    WHERE Gender = ‘female’
    ),
    MaleRows AS(
    SELECT *
    FROM SimpleTable
    WHERE Gender = ‘male’
    )
    UPDATE SimpleTable
    SET Gender = CASE
    WHEN st.Gender = FemaleRows.Gender THEN MaleRows.Gender
    WHEN st.Gender = MaleRows.Gender THEN FemaleRows.Gender
    ELSE st.Gender
    END
    FROM SimpleTable st,
    FemaleRows,
    MaleRows

    SELECT *
    FROM SimpleTable

    Reply
  • /*
    Using Replace in a way that can be applied for any given values to be swapped

    I’ve specifically considered ‘gent’ and ‘lady’ as there is no commonality between these words
    */

    create table #temp(id int, datacolumn char(4))
    insert into #temp
    values(1,’gent’),(2,’lady’),(3,’lady’)

    declare @value1 char(4), @value2 char(4)
    set @value1 = ‘lady’
    set @value2 = ‘gent’

    update #temp
    set datacolumn = replace(@value1 + @value2,datacolumn,”)

    Reply
  • /*
    1. A generic solution to swap any two values
    2. I’ve specifically considered ‘gent’ and ‘lady’ as there is no commanality between words. And the solution still works.
    3. Lastly, I’m sure you’ll consider that the way I’m using replace is not the same way as you have shown in your example. BTW even before looking at your solution the below was the solution I came up with. :-)
    */
    create table #temp(id int, datacolumn char(4))
    insert into #temp
    values(1,’gent’),(2,’lady’),(3,’lady’)

    declare @value1 char(4), @value2 char(4)
    set @value1 = ‘lady’
    set @value2 = ‘gent’

    update #temp
    set datacolumn = replace(@value1 + @value2,datacolumn,”)

    Reply
  • SIJIN KUMAR V P
    June 8, 2012 10:10 am

    Here it is ,By using RIGHT(),DIFFERENCE() and SOUNDEX ()

    UPDATE SimpleTable
    SET Gender = RIGHT((‘fe’+Gender), DIFFERENCE((Gender),SOUNDEX(Gender))*2)

    Reply
  • SIJIN KUMAR V P
    June 8, 2012 10:24 am

    By using COALESCE() and NULLIF()

    UPDATE SimpleTable
    SET Gender = COALESCE(NULLIF(‘female’,Gender), ‘male’)

    Reply
  • Using an innser Join

    UPDATE T
    SET T.GENDER = S.GENDER
    FROM SimpleTable S INNER JOIN SimpleTable T
    ON T.Gender S.Gender

    Reply
  • harshcontractor
    June 8, 2012 10:44 am

    UPDATE S
    SET S.Gender = (SELECT DISTINCT Gender FROM SimpleTable AS S1 WHERE (S.Gender S1.Gender))
    FROM SimpleTable AS S

    Reply
  • SIJIN KUMAR V P
    June 8, 2012 10:44 am

    By using SUBSTRING(),ABS() and DIFFERENCE()

    UPDATE SimpleTable
    SET Gender = SUBSTRING((‘female’),ABS(DIFFERENCE(‘male’,Gender)-5),6)

    Reply
  • Navneet Chaurasia
    June 8, 2012 10:56 am

    Thank u so much Sir jee…….N all of U, for such nice solutions of my problem……..

    Reply
  • harshcontractor
    June 8, 2012 10:59 am

    UPDATE SimpleTable
    SET Gender = RIGHT(‘female’, 10 – LEN(Gender))

    Reply
  • Hemant Yadav
    June 8, 2012 11:08 am

    Here same as Case statement

    UPDATE SimpleTable SET Gender = IF(Gender = ‘Male’, Female’, IF(color =
    ‘Female’, ‘Male’, Gender ))

    Reply
  • /*
    Another approach
    1. Update to some default value
    2. Then figure out all rows that were not updated and update them to the next value.
    */
    create table #temp(id int, datacolumn char(4))

    insert into #temp
    values(1,’lady’),(2,’gent’),(3,’lady’)

    declare @vartbl table(beforeupdate char(4), afterupdate char(4), id int)

    declare @value1 char(4), @value2 char(4)
    set @value1 = ‘lady’
    set @value2 = ‘gent’

    update #temp
    set datacolumn = @value1
    output deleted.datacolumn,inserted.datacolumn,inserted.id
    into @vartbl

    update #temp
    set datacolumn = @value2
    where exists(select null from @vartbl tbl where beforeupdate = afterupdate
    and #temp.id = tbl.id)

    Reply
  • Another solution can be using computed column(non persisted).
    Declare @SimpleTable TABLE (ID INT, Gender VARCHAR(10),SwapCol as
    Case when gender=’male’ then ‘female’else ‘male’ End)

    I think thomas first method in this post is ok.

    Reply

Leave a Reply