How does this CASE expression reach the ELSE clause?

前端 未结 3 1339
无人及你
无人及你 2020-11-29 07:18

I need to load some test data into the Channel field on my Account table. The Channel can be one of 10 different values, so I thought I\'d randomly assign the Channel one o

相关标签:
3条回答
  • 2020-11-29 08:04

    A new "random" number will be calculated for every WHEN clause - you can instead use a derived table:

    SELECT ID, Name, 
        Channel = 
          CASE Rand
            WHEN 0 THEN 'Baby Only'
            WHEN 1 THEN 'Club'
            WHEN 2 THEN 'Drug'
            WHEN 3 THEN 'Food'
            WHEN 4 THEN 'Internet'
            WHEN 5 THEN 'Liquidators'
            WHEN 6 THEN 'Mass'
            WHEN 7 THEN 'Military'
            WHEN 8 THEN 'Other'
            WHEN 9 THEN 'Speciality'
            ELSE '*NONE*'            -- How is this ever getting reached?
          END
    FROM
    (   SELECT 
             id,
             name,
             ABS(CHECKSUM(NewId())) % 10 Rand
        FROM   
            retailshelf_nil...account A
    ) zzz;
    

    or a CROSS APPLY subquery:

    SELECT A.ID, A.Name, 
        Channel = 
          CASE zzz.Rand
            WHEN 0 THEN 'Baby Only'
            WHEN 1 THEN 'Club'
            WHEN 2 THEN 'Drug'
            WHEN 3 THEN 'Food'
            WHEN 4 THEN 'Internet'
            WHEN 5 THEN 'Liquidators'
            WHEN 6 THEN 'Mass'
            WHEN 7 THEN 'Military'
            WHEN 8 THEN 'Other'
            WHEN 9 THEN 'Speciality'
            ELSE '*NONE*'            -- How is this ever getting reached?
          END
    FROM
        retailshelf_nil...account A
    CROSS APPLY
    (   SELECT 
            ABS(CHECKSUM(NewId())) % 10
    ) zzz (Rand);
    

    That way NewID() is called only once per record.

    A similar scneario was resolved here.

    The T-SQL documentation explains this phenomenon (granted it's for Sybase but apparently still applies to SQL Server):

    Expressions that reference the rand function, the getdate function, and so on, produce different values each time they are evaluated. This can yield unexpected results when you use these expressions in certain case expressions. For example, the SQL standard specifies that case expressions with the form:

    case expression
        when value1 then result1
        when value2 then result2
        when value3 then result3
    ...
    end
    

    are equivalent to the following form of case expression:

    case expression
        when expression=value1 then result1
        when expression=value2 then result2
        when expression=value3 then result3
    ...
    end
    
    0 讨论(0)
  • 2020-11-29 08:08

    Related to second question,

    CHECKSUM(NewId()) will return negative results sometimes, which is not match with any of the case conditions. If a negative number is divided with any number the result will be negative. Execute the following query,

    declare @v nvarchar(50) = newid()
    select CHECKSUM(@v),@v,CHECKSUM(@v) % 10
    
    0 讨论(0)
  • 2020-11-29 08:14

    The written form of the query is expanded to:

    Channel = 
          CASE
            WHEN ABS(CHECKSUM(NewId())) % 10 = 0 THEN 'Baby Only'
            WHEN ABS(CHECKSUM(NewId())) % 10 = 1 THEN 'Club'
            WHEN ABS(CHECKSUM(NewId())) % 10 = 2 THEN 'Drug'
            WHEN ABS(CHECKSUM(NewId())) % 10 = 3 THEN 'Food'
            WHEN ABS(CHECKSUM(NewId())) % 10 = 4 THEN 'Internet'
            WHEN ABS(CHECKSUM(NewId())) % 10 = 5 THEN 'Liquidators'
            WHEN ABS(CHECKSUM(NewId())) % 10 = 6 THEN 'Mass'
            WHEN ABS(CHECKSUM(NewId())) % 10 = 7 THEN 'Military'
            WHEN ABS(CHECKSUM(NewId())) % 10 = 8 THEN 'Other'
            WHEN ABS(CHECKSUM(NewId())) % 10 = 9 THEN 'Speciality'
            ELSE '*NONE*'            -- How is this ever getting reached?
          END
    

    A new value for NEWID is used in each test.

    0 讨论(0)
提交回复
热议问题