3

我已经在这里大量简化了我的示例,所以如果它看起来对我要解决的问题来说很简单,请原谅。

是否可以根据行值将BETWEEN, 转换为 a (为简单起见,我在这里使用了一个变量),而无需重复 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”(我试图避免字符串动态 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'
) 
4

3 回答 3

7

我认为您只需要更多的括号...

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
于 2011-08-19T15:40:41.683 回答
1

希望这会有所帮助。

    SELECT Name, DOB FROM @TestTable WHERE 
CASE WHEN @is = 1 THEN DOB ELSE '1900' END BETWEEN '2011-08-18' AND '2012-08-18'
于 2011-08-19T16:02:55.803 回答
0

只需使用逻辑将它们组合成一个语句:

(@is = 1) = (DOB BETWEEN '2011-08-18' AND '2012-08-18') 

这表示双方的“真相”必须相同(两者都为假或均为真),这就是您的代码可以简化为的内容。

于 2011-08-19T15:44:39.063 回答