SQL: espressione CASE all'interno di WHERE
-
03-07-2019 - |
Domanda
Ho letto sull'uso dell'espressione CASE all'interno della clausola WHERE qui:
http: // scottelkin. com / sql / con-a-caso-dichiarazione-in-a-sql-dove-clausola /
Sto cercando di utilizzare questo per filtrare i risultati dalla mia dichiarazione selezionata, in base a un numero di contratto che verrà passato dall'applicazione dell'utente. Il mio codice attualmente genera un errore di "Parametro non valido", indipendentemente da ciò che viene passato. Ho verificato che SELECT / FROM funziona correttamente, come in una clausola WHERE senza un'espressione CASE. Ecco il mio codice.
WHERE (CASE WHEN @ContractNo = 0 THEN @ContractNo ELSE @ContractNo END =
tblContracts.ContractNo)
La ridondanza del codice è a scopo di risoluzione dei problemi, sto pianificando di utilizzare il filtro jolly sul CASE in seguito. Mi sto concentrando su come abbassare la sintassi in questo momento. Credo che questo dovrebbe restituire tutti i record per i quali il parametro corrisponde al numero di contratto memorizzato nella tabella. Qualsiasi aiuto o consiglio sarebbe molto apprezzato.
Soluzione
Dopo aver letto la tua spiegazione, c'è un modo migliore per farlo senza CASE
:
WHERE @ContractNo = 0 OR tblContracts.ContractNo = @ContractNo
Questo restituirà solo i numeri di contratto corrispondenti, a meno che @ContractNo
sia 0, nel qual caso restituirà tutti i record.
Modifica: ho appena notato che casperOne ha proposto la stessa cosa . Non l'ho visto. Cresci da soli.
Altri suggerimenti
Sei sicuro di voler fare questo? L'istruzione case restituisce SEMPRE @ContractNo
. Penso che quello che stai cercando sia questo:
where
case @ContractNo
when 0 then tblContracts.ContractNo
else @ContractNo
end = tblContracts.ContractNo
Il filtro sopra dice " dammi il contratto in cui ContractNo
è uguale al parametro, o tutti loro se il parametro è 0.
Il filtro precedente ha filtrato solo dove il campo del numero di contratto è esattamente uguale al parametro.
Indipendentemente da ciò, dovresti invece farlo:
where @ContractNo = 0 or @ContractNo = tblContracts.ContractNo
La logica è molto più facile da capire, e soprattutto (non citarmi su questo), l'ottimizzatore probabilmente funzionerà meglio al di fuori dell'istruzione case.
Prova a tralasciare le parentesi che si trovano comunque nel posto sbagliato - quella giusta dovrebbe essere dopo "END".
Forse hai dimenticato di dichiarare @ContractNo? È paragonabile a 0 e a tblContracts.ContractNo?
Il post di Recursive ha risolto il mio problema con precisione.
Ho visto lamentele sulla chiarezza del mio post originale. In futuro, cosa posso fare per rendere più semplice ciò che sto dicendo? Non sono abituato a formulare domande sul codice e mi scuso per le cose confuse che aveva. Ho solo bisogno di fornire i dettagli estesi come nel mio secondo post?
Grazie ancora per tutto l'aiuto.
Sposta la parentesi chiusa prima del = in questo modo:
WHERE (CASE WHEN @ContractNo = 0 THEN @ContractNo ELSE @ContractNo END)=tblContracts.ContractNo
Non riesco a vedere cosa farà questa dichiarazione del caso ... stai restituendo la stessa cosa nel caso in cui @ContractNo = 0 o se non lo è ...
La sintassi corretta è:
Select...
...
Where(
Case
When <Condition>
Then <Return if true>
Else <Return if false>
End
) = <Whatever is being matched to the output of the case statement>
Indipendentemente dalla sintassi, il tuo esempio non ha molto senso, se stai cercando tutti gli articoli che corrispondono o hanno un numero di contratto pari a 0, allora dovresti:
Select...
...
Where (
@ContractNo = 0 Or
@ContractNo = tblContracts.ContractNo
)
Il che sembra avere molto più senso di quello per cui stai tentando di utilizzare l'istruzione case.
Modifica: Devo aver letto male la domanda: il parametro mancante di solito significa che il parametro (in questo caso @ContractNo) non è dichiarato nell'ambito della tua query / procedura. Ma qualcuno l'ha già sottolineato, quindi non posso prendermi il merito.
Il motivo dell'istruzione case, incluso l'intero " Se è 0, indica il parametro e, in caso contrario, fornisci semplicemente il parametro " è stato testarlo per cercare di ottenere la sintassi corretta. Inizialmente, avevo provato a dire " Se è 0, passa '%', per restituire ogni valore. Il codice che ho inserito era perché continuavo a ricevere "Parametro non valido" e immaginavo che ci fosse qualcosa di sbagliato nella mia sintassi. Quando l'ho separato in corrispondenza dei parametri di base in questo modo,
WHERE @ContractNo = tblContracts.ContractNo
ha restituito i record benissimo. Lasciami spiegare un po 'di più.
Sto estraendo da un sacco di tabelle diverse e filtrando il contenuto con informazioni non incluse nell'istruzione select (cioè tblContracts non ha informazioni estratte da Select, è usato solo in Where). L'utente selezionerà da una casella combinata che avrà i diversi numeri di contratto, nonché un valore predefinito di "Tutti".
Avrò un evento per quando cambia l'indice della casella combinata. Se è "All", 0 verrà passato come parametro e non voglio che il filtro venga eseguito. Altrimenti, voglio solo le informazioni per quel numero di contratto (il motivo di Else @ContractNo).
Non intendi qualcosa del genere?
SELECT *
FROM tblContracts
WHERE
CASE
WHEN tblContracts.ContractNo = 0 THEN @ContractNo
ELSE tblContracts.ContractNo
END = tblContracts.ContractNo
Dove @ContractNo è una variabile dello stesso tipo di dati di tblContracts.ContractNo
Perché hai persino bisogno di un'istruzione case?
QUANDO @ContractNo = 0 allora (0 = tblContracts.ContractNo) else @ContractNo quindi (@ContractNo = tblContracts.ContractNo)
Questo non ha senso dal momento che potresti semplicemente scrivere questo come
Dove @contractNo = tblContracts.contractNo
Il numero del contratto è in realtà un numero o è una stringa che risulta essere sempre un numero. Controlla i tipi di dati tra la tabella e il parametro e l'istruzione CASE (ad esempio, " = 0 " o " = '0' ")
Questa sintassi dovrebbe funzionare (funziona in Oracle)
WHERE CASE WHEN tblContracts.ContractNo = 0
THEN @ContractNo
ELSE tblContracts.ContractNo
END = tblContracts.ContractNo
quando dici:
Sto estraendo da un sacco di tabelle diverse e filtrando il contenuto con informazioni non incluse nell'istruzione select (ovvero tblContracts non ha informazioni estratte da Select, viene utilizzato solo in Where). L'utente selezionerà da una casella combinata che avrà i diversi numeri di contratto, nonché un valore predefinito di "Tutti".
Quindi mi sembra che dovrebbe avere un " Dov'è " clausola. dal momento che non stai estraendo alcuna informazione da quel tavolo ?!