SQL 2008中使用CASE-THEN的复杂WHERE表达式

时间:2009-09-03 19:20:43

标签: sql tsql sql-server-2008

我有一个问题:

SELECT ID FROM requests WHERE date <operator> <expression>

我需要依赖我的存储过程参数来更改<expression>

如果设置了标志:WHERE date BETWEEN GETDATE() - 7 AND GETDATE()

如果不是:WHERE date = date

我试图使用CASE-THEN,但它强制使用具体的操作符,但我必须要少:

SELECT ID FROM requests WHERE date = -- here it is
CASE
  WHEN @flag = 1 THEN ..
  ELSE date
END

4 个答案:

答案 0 :(得分:3)

select 
    id
from
    requests
where
    (
        flag = 1
        and
        date between getdate()-7 and getdate()
    )
    or
    (
        flag <> 1
        and
        date = date
    )

答案 1 :(得分:1)

SELECT ID FROM requests WHERE 
    (date = date and @flag <> 1 ) 
    or ( date BETWEEN GETDATE() - 7 AND GETDATE() and @flag = 1)

或者在Transact-SQL

if @flag = 1
    then
     SELECT ID FROM requests WHERE date = date
    else
     SELECT ID FROM requests WHERE date BETWEEN GETDATE() - 7 AND GETDATE()

答案 2 :(得分:1)

您可以使用优质的旧IF语句来简化它

if @flag = 1
   SELECT ID FROM requests WHERE date BETWEEN GETDATE() - 7 AND GETDATE()
else
   SELECT ID FROM requests 
编辑:我不确定它是否有效。但是,这是我在评论中添加的内容

SELECT ID FROM requests 
WHERE 
CASE WHEN @flag = 1 THEN date BETWEEN GETDATE() - 7 AND GETDATE() 
ELSE 1 = 1 
END

EDIT2:我认为使用IF语句是有意义的(如果它在TSQL中)。因为,条件依赖于外部变量而不是行中的某些东西

即。 CASE将对每行进行@flag比较,这是不需要的。

答案 3 :(得分:1)

如您所知,您不能在WHERE子句中使用CASE语句。您的替代方案是:

选项1:WHERE子句

SELECT t.id 
  FROM REQUESTS t
 WHERE 1 = 1
    OR (@flag = 1 AND t.date BETWEEN GETDATE() - 7 AND GETDATE())

选项2:使用IF并具有两个(或更多取决于情况)不同的SQL语句

IF @flag = 1
   SELECT t.id 
     FROM REQUESTS t
ELSE
   SELECT t.id 
     FROM REQUESTS t
    WHERE t.date BETWEEN GETDATE() - 7 AND GETDATE())

选项3:动态SQL(每个人都喜欢的)

DECLARE @SQL nvarchar (4000)

SET @SQL = 'SELECT t.id 
              FROM REQUESTS t 
             WHERE 1 = 1'

IF @flag = 1 
  SET @SQL = @SQL + ' AND t.date BETWEEN GETDATE()-7 AND GETDATE()'

EXEC sp_executesql @SQL 

就个人而言,我不愿意处理选项2.几乎相同的语句使我想要重构为单个SQL查询。也就是说,如果事情不是太复杂,请使用#1。否则,请使用动态。