In che modo questa espressione CASE raggiunge la clausola ELSE?

Ho bisogno di caricare alcuni dati di test nel campo Canale sulla mia tabella Account. Il canale può essere uno tra 10 valori diversi, quindi ho pensato di assegnare casualmente al canale uno dei valori usando un’espressione CASE insieme a ABS(CHECKSUM(NewId())) % 10 modo:

 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 

Dal momento che sto usando modulo 10 ho pensato che gli unici valori possibili dovrebbero essere 0-9. Ma quando eseguo il codice di cui sopra, sto trovando che la clausola ELSE viene effettivamente raggiunta e che i miei dati stanno arrivando con “NONE” su alcuni record come mostrato:

 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 

Qualcuno può spiegare quale errore logico ho fatto che consente di ottenere la clausola ELSE?

Quando eseguo un semplice test per generare il numero casuale in questo modo:

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

Tutti i numeri generati sono da 0 a 9 come previsto, quindi cosa c’è di diverso in questo primo SQL?

E c’è una soluzione alternativa per garantire che ELSE non venga mai raggiunto?

La forma scritta della query è estesa a:

 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 

In ogni test viene utilizzato un nuovo valore per NEWID .

Un nuovo numero “casuale” verrà calcolato per ogni clausola WHEN – puoi invece utilizzare una tabella derivata:

 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; 

o una sottoquery CROSS APPLY:

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

In questo modo NewID() viene chiamato una sola volta per record.

Uno scneario simile è stato risolto qui .

La documentazione T-SQL spiega questo fenomeno (concesso è per Sybase ma apparentemente si applica ancora a SQL Server):

Le espressioni che fanno riferimento alla funzione rand , alla funzione getdate e così via, producono valori diversi ogni volta che vengono valutate. Ciò può produrre risultati imprevisti quando si utilizzano queste espressioni in determinate espressioni del caso. Ad esempio, lo standard SQL specifica le espressioni caso con il modulo:

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

sono equivalenti alla seguente forma di espressione del caso:

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

Relativo alla seconda domanda,

CHECKSUM (NewId ()) restituirà risultati negativi a volte, il che non corrisponde a nessuna delle condizioni del case . Se un numero negativo è diviso con un numero qualsiasi, il risultato sarà negativo. Esegui la seguente query,

 declare @v nvarchar(50) = newid() select CHECKSUM(@v),@v,CHECKSUM(@v) % 10