2013-09-05 3 views
39

Я создаю SQL-запрос, в котором мне нужен условный оператор where.Условное предложение WHERE в SQL Server

Это должно быть что-то вроде этого:

SELECT 
    DateAppr, 
    TimeAppr, 
    TAT, 
    LaserLTR, 
    Permit, 
    LtrPrinter, 
    JobName, 
    JobNumber, 
    JobDesc, 
    ActQty, 
    (ActQty-LtrPrinted) AS L, 
    (ActQty-QtyInserted) AS M, 
    ((ActQty-LtrPrinted)-(ActQty-QtyInserted)) AS N 
FROM 
    [test].[dbo].[MM] 
WHERE 
    DateDropped = 0 
      --This is where i need the conditional clause 
    AND CASE 
      WHEN @JobsOnHold = 1 THEN DateAppr >= 0 
      ELSE DateAppr != 0 
     END 

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

Я не хочу использовать динамический SQL, так есть ли другой способ или мне нужно использовать обходной путь, например, используя if else и используя тот же запрос с различными предложениями where?

+0

Изменение вопроса или кода (от 'DateAppr = 0' до' DateAppr> = 0') после того, как другие ответили ... Почему? –

+0

Извините! Я забыл, что на первом месте так просто исправил его –

ответ

52

Попробуйте

SELECT 
    DateAppr, 
    TimeAppr, 
    TAT, 
    LaserLTR, 
    Permit, 
    LtrPrinter, 
    JobName, 
    JobNumber, 
    JobDesc, 
    ActQty, 
    (ActQty-LtrPrinted) AS L, 
    (ActQty-QtyInserted) AS M, 
    ((ActQty-LtrPrinted)-(ActQty-QtyInserted)) AS N 
FROM 
    [test].[dbo].[MM] 
WHERE 
    DateDropped = 0 
    AND (
    (ISNULL(@JobsOnHold, 0) = 1 AND DateAppr >= 0) 
    OR 
    (ISNULL(@JobsOnHold, 0) != 1 AND DateAppr != 0) 
    ) 

You can read more about conditional WHERE here.

+3

По мере роста вашей таблицы вы захотите посмотреть производительность запроса, в результате которого вы получите, поскольку оптимизатор может стать довольно недовольны этими типами запросов. – GaTechThomas

7

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

Вам просто нужно использовать булеву логику (или, скорее, троичной логики, что SQL использует) и переписать его:

WHERE 
    DateDropped = 0 
AND (@JobsOnHold = 1 AND DateAppr >= 0 
    OR (@JobsOnHold <> 1 OR @JobsOnHold IS NULL) AND DateAppr <> 0 
    ) 
+0

Я ошибочно отредактировал ваше сообщение. Сожалею. – Devart

+0

Спасибо. Это хорошо ! –

+1

Просто запрос В соответствии с этой [ссылкой] (http://dba.stackexchange.com/a/5337/27862) ответ может быть случай, когда оба условия будут разрешены в использовании оператора AND, поэтому, если сначала один не удается, он может применить условие DateAppr = 0 правильно? –

21

Попробуйте один -

WHERE DateDropped = 0 
    AND (
     (ISNULL(@JobsOnHold, 0) = 1 AND DateAppr >= 0) 
     OR 
     (ISNULL(@JobsOnHold, 0) != 1 AND DateAppr != 0) 
    ) 
+0

Спасибо. Это хорошо ! –

+0

Добро пожаловать @Curiosity :) – Devart

+0

Просто запрос В соответствии с этой [link] (dba.stackexchange.com/a/5337/27862) ответом может быть случай, когда оба условия будут разрешены в использовании оператора AND, поэтому, если первый из них терпит неудачу, то также он может применить условие DateAppr = 0 правильно? –

6

Чтобы ответить на вопрос о том, как использовать выражение CASE в предложении WHERE:

Прежде всего помните, что значение выражения CASE должно иметь нормальное значение типа данных, а не булево значение. Это должен быть varchar, или int, или что-то еще. По той же причине вы не можете сказать SELECT Name, 76 = Age FROM [...] и рассчитываете получить 'Frank', FALSE в результирующем наборе.

Кроме того, все выражения в предложении WHERE должны иметь логическое значение. Они не могут имеют значение varchar или int. Вы не можете сказать WHERE Name; или WHERE 'Frank';. Вы должны использовать оператор сравнения, чтобы сделать его логическим выражением, поэтому WHERE Name = 'Frank';

Это означает, что выражение CASE должно быть на одной стороне булевого выражения. Вы должны сравнить выражение CASE с чем-то. Он не может стоять сам по себе!

Здесь:

WHERE 
    DateDropped = 0 
    AND CASE 
      WHEN @JobsOnHold = 1 AND DateAppr >= 0 THEN 'True' 
      WHEN DateAppr != 0 THEN 'True' 
      ELSE 'False' 
     END = 'True' 

Обратите внимание, как, в конце концов выражение СЛУЧАЙ на левой повернет логическое выражение в любом 'True' = 'True' или 'False' = 'True'.

Обратите внимание, что нет ничего особенного в отношении 'False' и 'True'. Вы также можете использовать 0 и 1, если хотите.

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

Смежные вопросы