Делать IF в SQL ГДЕ - PullRequest
       31

Делать IF в SQL ГДЕ

1 голос
/ 04 января 2010

Я хочу сделать это

SELECT *
  FROM sales_order_header       
 WHERE order_reference LIKE @order_reference + '%'
   AND ((@booked_in IS NULL) OR ( booked_in = @booked_in))
   AND ((@depot_assigned IS NULL) OR ( IF @depot_assigned = 'Y' depot_code <> ' ' ELSE depot_code = ' ') )

Я уверен, что вы все можете догадаться, что бит OR (IF @depot_assigned и т. Д.) Не работает.

Как я могу сделать что-то подобное или мне нужно сделать это как два отдельных оператора выбора в зависимости от значения параметра @depot_assigned.

Ответы [ 4 ]

7 голосов
/ 04 января 2010
SELECT
        *

    FROM
        sales_order_header

    WHERE
        order_reference LIKE @order_reference + '%'         AND
        ((@booked_in IS NULL) OR ( booked_in = @booked_in)) AND
        ((@depot_assigned IS NULL) OR 
            ( @depot_assigned = 'Y' AND depot_code <> ' ' ) OR
            ( @depot_assigned <> 'Y' AND depot_code = ' ') )
3 голосов
/ 04 января 2010

T-SQL CASE - это то, что вы ищете. Модификация вашего кода ниже должна работать для вас:

SELECT
    *
FROM
    sales_order_header

WHERE
    order_reference LIKE @order_reference + '%'         AND
    ((@booked_in IS NULL) OR ( booked_in = @booked_in)) AND
    ((@depot_assigned IS NULL) OR (CASE WHEN @depot_assigned = 'Y' THEN depot_code <> ' ' ELSE depot_code = ' ' END) )
0 голосов
/ 04 января 2010
SELECT * FROM sales_order_header       
WHERE 
order_reference LIKE @order_reference + '%'
AND 
booked_in = ISNULL(@booked_in,booked_in)
AND 
CASE 
    WHEN @depot_assigned IS NULL THEN 1 
    WHEN @depot_assigned  = 'Y' AND depot_code <> ' ' THEN 1 
    WHEN @depot_assigned <> 'Y' AND depot_code  = ' ' THEN 1
    ELSE 0 
END = 1

РЕДАКТИРОВАТЬ: похоже на некоторые другие ответы. Просто немного проще.

0 голосов
/ 04 января 2010

Когда вы создаете запрос, подобный тому, который вы пытаетесь, оптимизатору запросов потребуется создать один план, чтобы соответствовать любому значению параметров. Это приведет к худшему из возможных планов. Таким образом, даже если вы придумали правильное выражение (используя CASE), запрос будет очень плохо выполняться из-за противоречивых условий ИЛИ.

Разделите операторы IF на условия SQL и используйте отдельные запросы для каждого случая:

IF @booked_in IS NULL and @depot_assigned IS NULL
  SELECT * FROM sales_order_header
  WHERE order_reference LIKE @order_reference + '%'
ELSE IF @depot_assigned IS NULL
  SELECT * FROM sales_order_header
  WHERE order_reference LIKE @order_reference + '%'
  AND booked_in = @booked_in
ELSE IF @booked_in IS NULL AND @depot_code='Y'
  SELECT * FROM sales_order_header
  WHERE order_reference LIKE @order_reference + '%'
  AND depot_code <> ' '
ELSE IF IF @booked_in IS NULL AND @depot_code<>'Y'
  SELECT * FROM sales_order_header
  WHERE order_reference LIKE @order_reference + '%'
  AND depot_code = ' '
ELSE IF @depot_code = 'Y'
  SELECT * FROM sales_order_header
  WHERE order_reference LIKE @order_reference + '%'
  AND booked_in = @booked_in
  AND depot_code <> ' '
ELSE
  SELECT * FROM sales_order_header
  WHERE order_reference LIKE @order_reference + '%'
  AND booked_in = @booked_in
  AND depot_code = ' '

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

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

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