2013-09-05 16 views
39

Sto creando una query SQL in cui ho bisogno di una clausola condizionale where.Clausola WHERE condizionale in SQL Server

dovrebbe essere qualcosa di simile:

SELECT 
    DateAppr, 
    TimeAppr, 
    TAT, 
    LaserLTR, 
    Permit, 
    LtrPrinter, 
    JobName, 
    JobNumber, 
    JobDesc, 
    ActQty, 
    (ActQty-LtrPrinted) AS L, 
    (ActQty-QtyInserted) AS M, 
    ((ActQty-LtrPrinted)-(ActQty-QtyInserted)) AS N 
FROM 
    [test].[dbo].[MM] 
WHERE 
    DateDropped = 0 
      --This is where i need the conditional clause 
    AND CASE 
      WHEN @JobsOnHold = 1 THEN DateAppr >= 0 
      ELSE DateAppr != 0 
     END 

La query sopra non funziona. Non è questa la sintassi corretta o c'è un altro modo per farlo che non conosco?

Non voglio utilizzare SQL dinamico, quindi esiste un altro modo o devo utilizzare una soluzione alternativa come utilizzare if else e utilizzare la stessa query con diverse clausole where?

+0

Cambiare la domanda o il codice (da 'DateAppr = 0' a' DateAppr> = 0') dopo che gli altri hanno risposto ... Perché? –

+0

Siamo spiacenti! L'ho dimenticato in primo luogo, quindi l'ho corretto solo –

risposta

52

Prova questa

SELECT 
    DateAppr, 
    TimeAppr, 
    TAT, 
    LaserLTR, 
    Permit, 
    LtrPrinter, 
    JobName, 
    JobNumber, 
    JobDesc, 
    ActQty, 
    (ActQty-LtrPrinted) AS L, 
    (ActQty-QtyInserted) AS M, 
    ((ActQty-LtrPrinted)-(ActQty-QtyInserted)) AS N 
FROM 
    [test].[dbo].[MM] 
WHERE 
    DateDropped = 0 
    AND (
    (ISNULL(@JobsOnHold, 0) = 1 AND DateAppr >= 0) 
    OR 
    (ISNULL(@JobsOnHold, 0) != 1 AND DateAppr != 0) 
    ) 

You can read more about conditional WHERE here.

+3

Man mano che la tabella cresce, ti consigliamo di guardare il rendimento della query che hai finito, perché l'ottimizzatore può diventare piuttosto insoddisfatto di questi tipi di query. – GaTechThomas

7

Il problema con la query è che in CASE espressioni, le parti THEN e ELSE avere un'espressione che restituisce un numero o un varchar o qualsiasi altro tipo di dati, ma non a un valore booleano.

Hai solo bisogno di usare la logica booleana (o meglio la logica ternaria che SQL utilizza) e riscriverla:

WHERE 
    DateDropped = 0 
AND (@JobsOnHold = 1 AND DateAppr >= 0 
    OR (@JobsOnHold <> 1 OR @JobsOnHold IS NULL) AND DateAppr <> 0 
    ) 
+0

ho erroneamente modificato il tuo post. Scusate. – Devart

+0

Grazie. Questo è buono ! –

+1

Solo una domanda In base a questa risposta [link] (http://dba.stackexchange.com/a/5337/27862) potrebbe esserci un caso in cui entrambe le condizioni verranno risolte nell'uso dell'operatore AND quindi se il primo fallisce allora anche può applicare la condizione DateAppr = 0 giusto? –

21

provare questo -

WHERE DateDropped = 0 
    AND (
     (ISNULL(@JobsOnHold, 0) = 1 AND DateAppr >= 0) 
     OR 
     (ISNULL(@JobsOnHold, 0) != 1 AND DateAppr != 0) 
    ) 
+0

Grazie. Questo è buono ! –

+0

Siete i benvenuti @Curiosity :) – Devart

+0

Solo una query Secondo questa risposta [link] (dba.stackexchange.com/a/5337/27862) potrebbe esserci un caso in cui entrambe le condizioni verranno risolte in AND user use quindi se prima fallisce allora anche può applicare la condizione DateAppr = 0 giusto? –

6

Per rispondere alla domanda sottostante su come usare un'espressione CASE nella clausola WHERE:

Innanzitutto, ricordare che il valore di un'espressione CASE deve avere un valore di tipo di dati normale, non un valore booleano. Deve essere un varchar, o un int, o qualcosa del genere. È lo stesso motivo per cui non puoi dire SELECT Name, 76 = Age FROM [...] e aspettati di ottenere 'Frank', FALSE nel set di risultati.

Inoltre, tutte le espressioni in una clausola WHERE necessità di avere un valore booleano. Loro non possono avere un valore di un varchar o di un int. Non puoi dire WHERE Name; o WHERE 'Frank';. È necessario utilizzare un operatore di confronto per trasformarlo in un'espressione booleana, quindi WHERE Name = 'Frank';

Ciò significa che l'espressione CASE deve essere su un lato di un'espressione booleana. Devi confrontare l'espressione CASE con qualcosa. Non può stare da solo!

Qui:

WHERE 
    DateDropped = 0 
    AND CASE 
      WHEN @JobsOnHold = 1 AND DateAppr >= 0 THEN 'True' 
      WHEN DateAppr != 0 THEN 'True' 
      ELSE 'False' 
     END = 'True' 

Si noti come, alla fine, l'espressione CASE sulla sinistra si accende l'espressione booleana in entrambi i 'True' = 'True' o 'False' = 'True'.

Nota che non c'è niente di speciale 'False' e 'True'. Puoi usare 0 e 1 se preferisci anche tu.

in genere è possibile riscrivere l'espressione CASE in espressioni booleane siamo più familiarità con, e questo è generalmente migliore per le prestazioni. Tuttavia, a volte è più facile o più gestibile utilizzare un'espressione esistente piuttosto che convertire la logica.