Операторы SQL как текст в предложении where - PullRequest
0 голосов
/ 27 июня 2011

У меня есть следующая таблица, которая используется для хранения бинтов. Таблица поддерживается через веб-интерфейс.

CREATE TABLE [dbo].[Banding](
[BandingID] [int] IDENTITY(1,1) NOT NULL,
[ValueLowerLimitOperator] [varchar](10) NULL,
[ValueLowerLimit] [decimal](9, 2) NULL,
[ValueUpperLimitOperator] [varchar](10) NULL,
[ValueUpperLimit] [decimal](9, 2) NULL,
[VolumeLowerLimitOperator] [varchar](10) NULL

В полях оператора хранятся такие значения, как> <> = <=. Я хочу попасть в положение, где я могу использовать значения операторов, хранящиеся в таблице, в операторе case в предложении where. Вот так. </p>

SELECT * FROM table WHERE CASE ValueLowerLimitOperator
WHEN '<' THEN VALUE < X
WHEN '>' THEN VALUE > X END

вместо того, чтобы писать несколько регистров или операторов if для каждой перестановки.

У кого-нибудь есть предложения, как я могу декодировать значения операторов, хранящиеся в таблице, как часть моего запроса, а затем использовать их в операторе case / where?

Ответы [ 3 ]

2 голосов
/ 27 июня 2011

Есть несколько техник, но есть кое-что, о чем нужно знать; Попытка сжать два типа функциональности в одном запросе часто приводит к плохим планам выполнения. (Например, сканирование таблицы или индекса, а не поиск индекса).

Мне часто бывает лучше переосмыслить структуру данных и / или переосмыслить, как формировать запрос.


Отвечая на конкретный пример в вашем вопросе, я бы сделал это ...

WHERE
  CASE WHEN VALUE < X THEN 1
       WHEN VALUE = X THEN 2
       WHEN VALUE > X THEN 4
  END
  |
  CASE ValueLowerLimitOperator
       WHEN '<'       THEN 1
       WHEN '<='      THEN 3
       WHEN '='       THEN 2
       WHEN '>='      THEN 6
       WHEN '>'       THEN 4
  END
  <>
  0

Однако, безусловно, не будут использованы какие-либо индексы.

Другой вариант - просто кодировать каждый сценарий ...

WHERE
  CASE ValueLowerLimitOperator
       WHEN '<'       THEN CASE WHEN VALUE <  X THEN 1 ELSE 0 END
       WHEN '<='      THEN CASE WHEN VALUE <= X THEN 1 ELSE 0 END
       WHEN '='       THEN CASE WHEN VALUE =  X THEN 1 ELSE 0 END
       WHEN '>='      THEN CASE WHEN VALUE >= X THEN 1 ELSE 0 END
       WHEN '>'       THEN CASE WHEN VALUE >  X THEN 1 ELSE 0 END
  END
  =
  1

Или, возможно, несколько объединенных запросов

WITH main_query AS (SELECT * FROM blah)
SELECT * FROM main_query WHERE ValueLowerLimitOperator = '<'  AND VALUE <  X
UNION ALL
SELECT * FROM main_query WHERE ValueLowerLimitOperator = '<=' AND VALUE <= X
UNION ALL
SELECT * FROM main_query WHERE ValueLowerLimitOperator = '='  AND VALUE =  X
UNION ALL
SELECT * FROM main_query WHERE ValueLowerLimitOperator = '>=' AND VALUE >= X
UNION ALL
SELECT * FROM main_query WHERE ValueLowerLimitOperator = '>'  AND VALUE >  X

Может быть, даже использовать функцию для декодирования всего этого?

SELECT
  *
FROM
  main_query
CROSS APPLY
  dbo.my_function(ValueLowerLimitOperator, VALUE, X) AS check
WHERE
  check.return_value = 1

(Using CROSS APPLY with a Inline Table Valued Function will be MUCH faster than a Scalar Function in the WHERE clause)

Когда вы выглядите так, как будто вы хотите, чтобы это повторилось для LowerLimit, UpperLimit и т. Д., Инкапсуляция этого в функцию кажется хорошей идеей для меня.

1 голос
/ 27 июня 2011

Почему бы не поставить значения:

1 для>, -1 для <, 2 для> =, -2 для <=, 0 для = </p>

, а затем попробуйте проверить результат

value * ValueLowerLimitOperator  -x*(ValueLowerLimitOperator)

Вы можете выбрать вот так:

select *
from table
where 1=
case 
when (value * ValueLowerLimitOperator  -x*ValueLowerLimitOperator >=0 and abs(ValueLowerLimitOperator)>1)      
    --that means it is <= or >= and the condition is true.
or (value * ValueLowerLimitOperator -x*ValueLowerLimitOperator >0 and abs(ValueLowerLimitOperator)=1)
   --that means it is < or >  and the condition is true.
or (value =x and ValueLowerLimitOperator=0)
   --that means it is = and the condition is true.
then 1
end

Это сделает это.

1 голос
/ 27 июня 2011

Вам понадобится динамический sql .Без большей информации, хотя я не могу дать вам больше примера, чем в ссылке

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