T-SQL - 在WHERE子句中使用CASE和参数

时间:2011-06-06 15:55:41

标签: sql sql-server sql-server-2008 stored-procedures case

我正在Sales表上运行报告:

SaleId INT | SalesUserID INT | SiteID INT | BrandId INT| SaleDate DATETIME

我正在做一个噩梦,尝试使用一组可以为空的参数@SalesUserID@SiteId@BrandID和两个DateTime参数进行类似的操作。

附加点:只有一个过滤器参数将作为非空值传递。

SELECT * from Sales
WHERE
     SaleDate BETWEEN @StartDate AND @EndDate

AND
    SalesUserID IN
(
    Select SalesUserID FROM Sales
    WHERE
        SaleDate BETWEEN @StartDate AND @EndDate

    AND

        CASE
            WHEN @SalesUserId IS NOT NULL THEN SalesUserId = @SalesUserID
            WHEN @SiteId Is Not Null THEN SiteId = @SiteId
            ELSE BrandId = @BrandID
        END

)

我在这里使用CASE闻起来很糟糕,但我不确定如何纠正它。你能帮忙吗?

感谢。

5arx

7 个答案:

答案 0 :(得分:8)

我认为你根本不想要一个CASE声明,而是一个复合条件...给我一个机会让我知道:

select * 
from Sales
where SaleDate between @StartDate and @EndDate
and
   (
    (@SalesUserId is not null and SalesUserId = @SalesUserID)
    or (@SiteId is not null and SiteId = @SiteId)
    or (BrandId = @BrandID)
   )    

答案 1 :(得分:6)

如果我理解正确,您希望三个条件为NULL或检查:

WHERE
    /* ... */
    AND SalesUserId = ISNULL(@SalesUserId, SalesUserId)
    AND SiteId      = ISNULL(@SiteId, SiteId)
    AND BrandId     = ISNULL(@BrandID, BrandID)

请注意,这会强制进行表扫描,这可能不符合您的最佳利益。

答案 2 :(得分:3)

如果您想使用CASE

,这应该可以使用任何索引
SELECT * 
from Sales 
WHERE SaleDate BETWEEN @StartDate AND @EndDate 
AND SalesUserID = CASE WHEN @SalesUserID IS NULL THEN 
SalesUserID ELSE @SalesUserID END

答案 3 :(得分:2)

COALESCE()返回第一个非NULL参数,因此可以;

...
WHERE SaleDate BETWEEN @StartDate AND @EndDate
  AND SalesUserId = COALESCE(@SalesUserId, SalesUserId)
  AND SiteId = COALESCE(@SiteId, SiteId)
  AND BrandID = COALESCE(@BrandID, BrandId)

答案 4 :(得分:2)

我会在这种情况下使用动态生成的代码:

declare @SalesUserId int,@SiteId int,@StartDate datetime, @EndDate datetime,@BrandID int
declare @sql nvarchar(max)

    set @sql = N'
    SELECT * from Sales
    WHERE
         SaleDate BETWEEN @StartDate AND @EndDate

    AND
        SalesUserID IN
    (
        Select SalesUserID FROM Sales
        WHERE
            SaleDate BETWEEN @StartDate AND @EndDate AND
    ' +
            CASE
                WHEN @SalesUserId IS NOT NULL THEN 'SalesUserId = @SalesUserID'
                WHEN @SiteId Is Not Null THEN 'SiteId = @SiteId'
                ELSE 'BrandId = @BrandID'
            END

    +')'

    print @sql

    exec sp_executesql @sql
        , N'@SalesUserId int,
            @SiteId int,
            @StartDate datetime,
            @EndDate datetime,
            @BrandID int'
            ,@SalesUserId
            ,@SiteId
            ,@StartDate
            ,@EndDate
            ,@BrandID

答案 5 :(得分:1)

如果您想要性能,这通常是动态SQl的工作。

http://www.sommarskog.se/dynamic_sql.html

答案 6 :(得分:1)

试试这个:

SELECT * 
from Sales 
WHERE SaleDate BETWEEN @StartDate AND @EndDate 
AND SalesUserID = CASE WHEN @SalesUserID IS NULL THEN 
SalesUserID ELSE @SalesUserID END