我在这里大量简化了我的例子,所以请原谅,如果它看起来很简单,我想解决的问题。
是否可以将BETWEEN
转换为NOT BETWEEN
,具体取决于行值(为简单起见,我在这里使用了一个变量),而不重复之间的语句?
我理解使用case语句和布尔逻辑来帮助使静态sql更“动态”,但我似乎无法找到像BETWEEN
这样的运算符的方法。
也许使用一些聪明的按位操作?
我在开发中有一些基于集合的SQL已经变得难以管理,所以我希望通过避免重复来简化它。
我正在尝试以基于SET的方式进行,如果可能的话,避免使用UDF。
DECLARE @is int
set @is = 1
DECLARE @TestTable TABLE
(
Name varchar(100),
DOB datetime
)
INSERT INTO @TestTable(Name, DOB)
SELECT 'bob', '2011-08-18 10:10:10.100' UNION ALL
SELECT 'fred', '2014-08-18 10:10:10.100'
SELECT Name, DOB
FROM @TestTable
WHERE
(@is = 1) AND (DOB BETWEEN '2011-08-18' AND '2012-08-18')
OR
(@is = 0) AND (DOB NOT BETWEEN '2011-08-18' AND '2012-08-18')
所以在上面的例子中,如果@is = 1,则返回bob。 如果@is = 0,则返回fred。
编辑: 为了澄清,上述声明工作正常,但我正在尝试对其进行优化,以避免编写2个BETWEEN语句。我希望根据@is的值来翻转逻辑....使用is来放入NOT。
编辑2:
请参阅下面的一些伪代码,了解我正在努力实现的目标。它是伪的,因为t-SQL不允许在这样的基于集合的操作中将“NOT”“注入”代码中(我试图避免使用stringy-dynamic sql)。
SELECT Name, DOB
FROM @TestTable
WHERE
(
DOB
CASE @is
WHEN 0
THEN NOT ---pseudo code, this won't actually work, but gives an idea of what I'm trying to achieve.
END
BETWEEN '2011-08-18' AND '2012-08-18'
)
答案 0 :(得分:7)
我认为你只需要更多的parens ......
WHERE
( (@is = 1) AND (DOB BETWEEN '2011-08-18' AND '2012-08-18') )
OR
( (@is = 0) AND (DOB NOT BETWEEN '2011-08-18' AND '2012-08-18') )
修改强>
知道了 - 所以这样的事情:
WHERE @is = CASE WHEN DOB BETWEEN '2011-08-18' AND '2012-08-18' THEN 1 ELSE 0 END
答案 1 :(得分:1)
希望这会有所帮助。
SELECT Name, DOB FROM @TestTable WHERE
CASE WHEN @is = 1 THEN DOB ELSE '1900' END BETWEEN '2011-08-18' AND '2012-08-18'
答案 2 :(得分:0)
只需使用逻辑将它们组合成一个语句:
(@is = 1) = (DOB BETWEEN '2011-08-18' AND '2012-08-18')
这表示双方的“真相”必须相同(无论是假的还是两者都是真的),这就是你的代码可以减少到的。