Переключить регистр / If в предложении where - PullRequest
4 голосов
/ 27 мая 2011

Я пытаюсь изменить условия ЧАСТИ где, основываясь на некотором значении.Я просмотрел похожие статьи здесь, в том числе:

Переключатель SQL / регистр, в котором предложение

Но они не совсем касаются моего случая.

У меня есть хранимая процедура, которая делает выбор на основе своих входных данных.Эти входные данные являются необязательными (или имеют параметры по умолчанию, так как они предпочитают вызывать их).

2 из указанных параметров являются числами.

  • если указано только первое число, столбец X долженравно этому числу.
  • , если указано первое и второе число, тогда столбец X должен быть> = первому И <= второму. </li>
  • , если указано только второе число, это НЕВЕРНО.

Это то, что я пытался (что, очевидно, не сработало)

DECLARE @SECOND INT;
DECLARE @FIRST INT;

SET @FIRST = 123456;
SET @SECOND = 67890;

SELECT * FROM BANK_DETAIL 
WHERE -- POSSIBLY SOME OTHER WHERE CLAUSES
    CASE
        WHEN @SECOND IS NULL THEN 
            X = @FIRST
        ELSE 
            X >= @FIRST AND X <= @SECOND 
    END
        -- POSSIBLY SOME MORE WHERE CLAUSES
ORDER BY X

REALLY такое ощущение, что ему нужен IF / ELSE, а неCASE, но я был направлен в CASE .....

О, это MS SQL> = 2005

Ответы [ 5 ]

4 голосов
/ 27 мая 2011

Попробуйте использовать недействительность @SECOND вместо CASE.

SELECT *
FROM BANK_DETAIL
WHERE
-- other conditions go here
AND ((@SECOND IS NULL AND X = @FIRST)
  OR (@SECOND IS NOT NULL AND X >= @FIRST AND X <= @SECOND))
3 голосов
/ 27 мая 2011
SELECT * FROM BANK_DETAIL 
WHERE
    (@SECOND IS NULL AND X = @FIRST) or
    (X >= @FIRST AND X <= @SECOND)

хотя было бы эффективнее:

IF @SECOND IS NULL
BEGIN
   SELECT * FROM BANK_DETAIL 
   WHERE
     X = @FIRST
END
ELSE
BEGIN
   SELECT * FROM BANK_DETAIL 
   WHERE
     X >= @FIRST AND X <= @SECOND
END
2 голосов
/ 27 мая 2011

Я бы использовал логические операторы:

SELECT * FROM BANK_DETAIL 
WHERE
  ((@SECOND IS NULL AND X = @FIRST) OR 
  (@SECOND IS NOT NULL AND X >= @FIRST AND X <= @SECOND));
1 голос
/ 27 мая 2011

Вы создаете условие динамического поиска .Вынуждая одно единственное утверждение покрывать оба случая, вы сокращаете параметры оптимизатора.Сгенерированный план должен работать в обоих случаях, когда @seconds равно нулю и когда не равно нулю.Вы будете намного лучше, если будете использовать два отдельных утверждения:

IF @SECOND IS NULL THEN
   SELECT * FROM BANK_DETAIL 
   WHERE  X = @FIRST
   ORDER BY X
ELSE
   SELECT * FROM BANK_DETAIL 
   WHERE X >= @FIRST AND X <= @SECOND 
   ORDER BY X

Ваша интуитивная «упрощение» в одно утверждение ведет вас по неверному пути.Результат - меньше текста, но гораздо больше времени выполнения из-за неоптимальных планов.Статья, на которую ссылается в начале моего ответа, подробно описывает эту тему.

0 голосов
/ 27 мая 2011

Проблема в том, что CASE возвращает значение, это не ветвь в логике.Ссылка, которую обеспечивает OMG, в значительной степени является авторитетным источником (почти все, что от Эрланда Соммарского может быть отличным советом).

Краткий обзор ссылки:

Вы можете использоватьдинамический SQL, где вы строите оператор на основе условий.Часто это может быть наилучшим подходом, но есть и недостатки.Один из самых больших недостатков - возможные проблемы безопасности, поэтому убедитесь, что вы полностью понимаете атаки с использованием SQL-инъекций и способы их предотвращения.

Другой подход заключается в использовании сложной логики в выражении WHERE с использованием OR.В вашем случае это будет что-то вроде ниже.Этот подход немного проще, чем динамический SQL, и безопаснее, но производительность не всегда может быть высокой.Если производительность подходит для вашей ситуации, хотя бы (протестируйте ее), то придерживайтесь этого подхода.

SELECT
    *    -- I assume that you used * just as an example and don't actually use this in your production code
FROM
    Bank_Detail
WHERE -- POSSIBLY SOME OTHER WHERE CLAUSES
    (@second IS NULL AND X = @first) OR
    (@second IS NOT NULL AND (x >= @first AND x <= @second))
    -- POSSIBLY SOME MORE WHERE CLAUSES
ORDER BY
    x

Другой способ организовать утверждение только что пришел мне в голову ...

SELECT
    *
FROM
    Bank_Detail
WHERE -- POSSIBLY SOME OTHER WHERE CLAUSES
    x >= @first AND
    x <= COALESCE(@second, @first)
    -- POSSIBLY SOME MORE WHERE CLAUSES
ORDER BY
    x

Iеще не проверял, но я думаю, что это будет логически эквивалентно и может дать вам более согласованный план запросов.

Эрланд также предлагает несколько других возможных подходов, поэтому обязательно прочитайте его полную статью опредмет.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...