복붙노트

[SQL] 어떻게 CASE 표현식은 ELSE 절에 도달 하는가?

SQL

어떻게 CASE 표현식은 ELSE 절에 도달 하는가?

내 계정 테이블에 채널 필드에 테스트 데이터를로드해야합니다. 나는 무작위로 ABS (CHECKSUM (NEWID ())) 10 % 때문에 같은과 함께 CASE 식을 사용하여 값의 채널 하나를 할당 할 거라고 생각 때문에 채널, 10 개 개의 값 중 하나 일 수 있습니다 :

SELECT 
    id,
    name,
    Channel = 
      CASE ABS(CHECKSUM(NewId())) % 10
        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

내가 모듈 (10)을 사용하고 있기 때문에 내가 유일하게 가능한 값은 0-9이어야한다 생각했다. 나는 위의 코드를 실행할 때, 나는 같이 내 데이터가 일부 레코드에 'NONE'으로 다가오고 있다는 ELSE 절은 참으로 도달되고 있음을 발견하고 해요 :

id                  name    Channel
001L000000KpgFqIAJ  Acct1   *NONE*
001L000000KpgFrIAJ  Acct2   Mass
001L000000KpgFsIAJ  Acct3   Club
001L000000KpgFtIAJ  Acct4   *NONE*
001L000000KpgFuIAJ  Acct5   Baby Only
001L000000KpgFvIAJ  Acct6   *NONE*
001L000000KpgFwIAJ  Acct7   Mass

누군가가 논리적 오류가 나는 ELSE 절을 수의에 도달 할 수 있다고했습니다 설명해 주시겠습니까?

나는 간단한 테스트를 실행할 때 너무 같은 난수를 생성합니다 :

SELECT
    RadomNum = ABS(CHECKSUM(NewId())) % 10
FROM 
    retailshelf_nil...account A
ORDER BY 
    1

생성 된 모든 숫자는 예상대로 0-9에서, 그래서 무슨 일이 첫 번째 SQL 다른 점?

그리고 도달하지 못했다되는 ELSE을 보장하는 해결 방법은?

해결법

  1. ==============================

    1.쿼리의 작성 양식으로 확장됩니다 :

    쿼리의 작성 양식으로 확장됩니다 :

    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
    

    NEWID에 대한 새로운 값은 각 시험에 사용된다.

  2. ==============================

    2.새로운 "임의의"번호는 각 WHEN 절에 대해 계산됩니다 - 대신 파생 테이블을 사용할 수 있습니다 :

    새로운 "임의의"번호는 각 WHEN 절에 대해 계산됩니다 - 대신 파생 테이블을 사용할 수 있습니다 :

    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;
    

    또는 CROSS는 하위 쿼리를 적용 :

    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);
    

    그 방법 NEWID ()는 레코드 당 한 번이라고합니다.

    비슷한 시나리오는 여기에 해결되었습니다.

    T-SQL 설명서는 (은 Sybase 용의하지만 분명히 여전히 SQL 서버에 적용 부여)이 현상을 설명합니다 :

  3. ==============================

    3.두 번째 질문에 관련,

    두 번째 질문에 관련,

    CHECKSUM (NEWID ()는) 경우의 조건 중 하나라도 일치하지 않는, 때로는 부정적인 결과를 반환합니다. 음수는 숫자로 나누면 결과는 음수가 될 것입니다. 다음 쿼리를 실행,

    declare @v nvarchar(50) = newid()
    select CHECKSUM(@v),@v,CHECKSUM(@v) % 10
    
  4. from https://stackoverflow.com/questions/21918536/how-does-this-case-expression-reach-the-else-clause by cc-by-sa and MIT license