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 7

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".

Может быть, вы забыли объявить @ContractNo? Сравним ли он с 0 и с tblContracts.Контрактно?

Сообщение рекурсивного точно решило мою проблему.

Я видел жалобы на ясность моего первоначального поста. В будущем, что я могу сделать, чтобы сделать то, что я говорю, более прямым? Я не привык формулировать вопросы о коде и извиняюсь за любые запутанные вещи, которые он имел. Мне просто нужно было предоставить расширенные детали, как в моем 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". так как ваш не тянет ни на что информация из этого стола?!