SQL-CASE выражение внутри WHERE
Я читал об использовании выражения CASE внутри предложения WHERE здесь:
Http://scottelkin.com/sql/using-a-case-statement-in-a-sql-where-clause/
Я пытаюсь использовать это для фильтрации результатов из моего оператора select, основываясь на номере контракта, который будет передан приложением пользователя. Мой код в настоящее время выдает ошибку "недопустимый параметр" независимо от того, что передается. Я проверил, что SELECT/FROM работают нормально, так как where как предложение WHERE без дела выражение. Вот мой код.
WHERE (CASE WHEN @ContractNo = 0 THEN @ContractNo ELSE @ContractNo END =
tblContracts.ContractNo)
Избыточность кода используется для устранения неполадок, позже я планирую использовать фильтрацию по шаблону в этом случае. Сейчас я сосредоточен на том, чтобы разобраться с синтаксисом. Я считаю, что это должно возвращать все записи, для которых параметр соответствует номеру контракта, хранящемуся в таблице. Любая помощь или совет будут очень признательны.
12 ответов:
После прочтения вашего объяснения, есть лучший способ сделать это без
CASE
:WHERE @ContractNo = 0 OR tblContracts.ContractNo = @ContractNo
Это вернет только совпадающие номера контрактов, если
@ContractNo
не равно 0, и в этом случае он вернет все записи.Edit: я только что заметил, чтокаспероне предложил то же самое . Я этого не видел. Ну-ка, повзрослей.
Вы уверены, что хотите это сделать? Ваше заявление case всегда возвращает
@ContractNo
. Я думаю, что вы ищете вот что:Фильтр выше говорит: "Дайте мне контракт, гдеwhere case @ContractNo when 0 then tblContracts.ContractNo else @ContractNo end = tblContracts.ContractNo
ContractNo
равен параметру, или все они, если параметр равен 0.Предыдущий фильтр фильтровал только там, где поле номер контракта точно равно параметру.
Несмотря на это, вы должны сделать это вместо:
where @ContractNo = 0 or @ContractNo = tblContracts.ContractNo
Логика гораздо проще для понимания, и на вершине из этого (не цитируйте меня по этому поводу) оптимизатор, вероятно, будет работать лучше вне оператора case.
Попробуйте опустить скобки, которые в любом случае находятся в неправильном месте - правильный должен быть после "END".
Сообщение рекурсивного точно решило мою проблему.
Я видел жалобы на ясность моего первоначального поста. В будущем, что я могу сделать, чтобы сделать то, что я говорю, более прямым? Я не привык формулировать вопросы о коде и извиняюсь за любые запутанные вещи, которые он имел. Мне просто нужно было предоставить расширенные детали, как в моем 2-м посте?
Еще раз спасибо за помощь.
Переместите закрывающую скобку в положение перед = примерно так:
WHERE (CASE WHEN @ContractNo = 0 THEN @ContractNo ELSE @ContractNo END)=tblContracts.ContractNo
Однако я не вижу, что будет делать это утверждение case... вы возвращаете то же самое в случае, если @ContractNo = 0 или если это не так...
Правильный синтаксис:
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>
Несмотря на синтаксис, ваш пример не имеет большого смысла, если вы ищете все элементы, которые соответствуют или имеют номер контракта 0, то вы бы сделали:
Select... ... Where ( @ContractNo = 0 Or @ContractNo = tblContracts.ContractNo )
Что, кажется, имеет гораздо больше смысла, чем то, для чего вы пытаетесь использовать оператор case.
Edit: я, должно быть, немного неправильно понял вопрос - отсутствующий параметр param обычно означает, что параметр (в данном случае @ContractNo) не объявлен в области вашего запроса/процедуры. Но кто-то уже указал на это, так что я не могу взять на себя ответственность за это.
Причина для оператора case, включая все "если это 0, дайте параметр, а в противном случае просто дайте параметр", состояла в том, чтобы проверить его, чтобы попытаться получить правильный синтаксис. Первоначально я пытался сказать: "если это 0, то передайте"%", чтобы вернуть все значения. Код, который я разместил там, был потому, что я продолжал получать "недопустимый параметр" и полагал, что должно быть что-то не так с моим синтаксисом. Когда я разделил его на основные параметры, соответствующие таким образом,
WHERE @ContractNo = tblContracts.ContractNo
Он вернул записи хорошо. Позвольте мне объяснить немного подробнее.
Я извлекаю из множества различных таблиц и фильтрую содержимое с информацией, не включенной в инструкцию select (т. е. tblContracts не имеет информации, извлеченной из нее Select, она используется только в Where). Пользователь выберет из выпадающего списка, который будет иметь различные номера контрактов, а также значение по умолчанию "все".
У меня будет событие, когда изменится индекс поля со списком. Если это "все", то 0 будет передано в качестве параметра, и я не хочу, чтобы фильтрация была выполнена. В противном случае, мне просто нужна информация для этого номера контракта (причина для Else @ContractNo).
Разве ты не имеешь в виду что-то вроде этого?
SELECT * FROM tblContracts WHERE CASE WHEN tblContracts.ContractNo = 0 THEN @ContractNo ELSE tblContracts.ContractNo END = tblContracts.ContractNo
Где @ContractNo-переменная того же типа данных, что и tblContracts.ContractNo
Зачем вам вообще нужен оператор case?
Когда @ContractNo = 0, ТО ( 0 = tblContracts.Контрактно) иначе @ContractNo тогда (@ContractNo = tblContracts.ContractNo)
Это не имеет смысла, так как вы можете просто написать это как
Где @contractNo = tblContracts.contractNo
Является ли номер контракта на самом деле числовым или это строка, которая всегда оказывается числовой. Проверьте типы данных между таблицей, параметром и оператором CASE (например, "= 0 " или "= '0'")
Этот синтаксис должен работать (он работает в Oracle)
WHERE CASE WHEN tblContracts.ContractNo = 0 THEN @ContractNo ELSE tblContracts.ContractNo END = tblContracts.ContractNo
Когда вы говорите:
Я извлекаю из множества различных таблиц и фильтрую содержимое с информацией, не включенной в инструкцию select (т. е. tblContracts не имеет информации, извлеченной из нее Select, она используется только в Where). Пользователь выберет из выпадающего списка, который будет иметь различные номера контрактов, а также значение по умолчанию "все".
Тогда мне кажется, что должно быть предложение" Where exists". так как ваш не тянет ни на что информация из этого стола?!