我有下表,用于存储条带。该表通过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语句中使用它们?
答案 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
这样就可以了。