SQL - CASE выражение внутри, где
-
03-07-2019 - |
Вопрос
Я читал об использовании выражения CASE внутри предложения WHERE:
http: // scottelkin. ком / SQL / с использованием-а-случай-заявление-в-SQL-где-пункт /
Я пытаюсь использовать это для фильтрации результатов из моего оператора выбора на основе номера контракта, который будет передан приложением пользователя. Мой код в настоящий момент выдает ошибку «Неверный параметр», независимо от того, что передано. Я проверил, что SELECT / FROM работают нормально, например, как предложение WHERE без выражения CASE. Вот мой код.
WHERE (CASE WHEN @ContractNo = 0 THEN @ContractNo ELSE @ContractNo END =
tblContracts.ContractNo)
Избыточность кода предназначена для устранения неполадок, я планирую использовать фильтрацию по шаблону на CASE позже. Я сосредоточен на снижении синтаксиса прямо сейчас. Я считаю, что это должно вернуть все записи, для которых параметр соответствует номеру контракта, хранящегося в таблице. Любая помощь или совет будет принята с благодарностью.
Решение
После прочтения вашего объяснения есть лучший способ сделать это без CASE
:
WHERE @ContractNo = 0 OR tblContracts.ContractNo = @ContractNo
Это вернет только совпадающие номера контракта, если @ContractNo
не равно 0, и в этом случае он вернет все записи.
Изменить . Я только что заметил, что casperOne предложил то же самое . Я этого не видел. Сделай сам.
Другие советы
Вы уверены, что хотите это сделать? Ваша выписка с делом ВСЕГДА возвращает @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.ContractNo?
Пост рекурсии решил мою проблему точно.
Я видел жалобы на ясность моего исходного поста. Что я могу сделать в будущем, чтобы сделать то, что я говорю, более понятным? Я не привык формулировать вопросы о коде и извиняться за любые запутанные вещи, которые у него были. Мне просто нужно было предоставить расширенную информацию, как в моем втором посте?
Еще раз спасибо за помощь.
Переместите закрывающую скобку до символа =, как показано ниже:
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: Я, должно быть, немного неправильно прочитал вопрос - отсутствующий параметр обычно означает, что параметр (в данном случае @ContractNo) не объявлен в объеме вашего запроса / процедуры. Но кто-то уже указывал на это, так что я не могу взять на себя ответственность за это.
Причина оператора case, включая целое " Если оно равно 0, укажите параметр, а в противном случае просто укажите параметр " было проверить его, чтобы попытаться получить правильный синтаксис. Первоначально я пытался сказать "Если это 0, то передайте"% ", чтобы вернуть каждое значение. Код, который я разместил там, был потому, что я продолжал получать «Неверный параметр» и решил, что с моим синтаксисом что-то не так. Когда я разделил его на базовое сопоставление параметров следующим образом,
WHERE @ContractNo = tblContracts.ContractNo
он вернул записи в порядке. Позвольте мне объяснить немного больше.
Я извлекаю данные из множества разных таблиц и фильтрую содержимое по информации, не включенной в оператор выбора (т. е. 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
Зачем вам вообще нужна выписка по делу?
WHen @ContractNo = 0 затем (0 = tblContracts.ContractNo) иначе @ContractNo then (@ContractNo = tblContracts.ContractNo)
Это не имеет смысла, так как вы можете просто написать это как
Где @contractNo = tblContracts.contractNo
Номер контракта на самом деле числовой или строка, которая всегда оказывается числовой. Проверьте ваши типы данных между таблицей и параметром и оператором CASE (например, "= 0" или "=" 0 ")
Этот синтаксис должен работать (он работает в Oracle)
WHERE CASE WHEN tblContracts.ContractNo = 0
THEN @ContractNo
ELSE tblContracts.ContractNo
END = tblContracts.ContractNo
когда вы говорите:
Я извлекаю данные из множества разных таблиц и фильтрую содержимое по информации, не включенной в оператор выбора (т. е. tblContracts не получает информацию, извлекаемую из него с помощью Select, она используется только в Where). Пользователь будет выбирать из поля со списком, в котором будут разные номера контрактов, а также значение по умолчанию «Все».
Тогда мне кажется, что должно быть "Где существует" пункт. так как вы не вытаскиваете какую-либо информацию из этой таблицы?!