SQL运算符作为where子句中的文本

时间:2011-06-27 11:28:06

标签: sql sql-server-2005 operators case

我有下表,用于存储条带。该表通过Web前端维护。

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

运营商字段存储诸如>之类的值。 < > =< =。我想到一个位置,我可以在where子句的case语句中使用存储在表中的运算符值。像这样。

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

而不是必须为每个排列写多个case或if语句。

有没有人有任何建议如何解码存储在表中的运算符值作为我的查询的一部分,然后在case / where语句中使用它们?

3 个答案:

答案 0 :(得分:2)

有几种技术,但有一些需要注意的事项;尝试将两种类型的功能压缩到单个查询中通常会导致执行计划不佳。 (例如,表或索引扫描,而不是索引搜索。)

我经常发现更好地重新考虑数据的设计,和/或重新考虑如何形成查询。


回答你问题中的具体例子,我会这样做......

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 :(得分:1)

您需要dynamic sql。没有更多信息,虽然我不能给你更多的例子而不是链接

答案 2 :(得分:1)

为什么不把值放在:

1表示&gt;,-1表示&lt;,2表示&gt; =,-2表示&lt; =,0表示=

然后尝试检查

的结果
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

这样就可以了。