T-SQL - Использование CASE с параметрами в предложении WHERE - PullRequest
4 голосов
/ 06 июня 2011

Я запускаю отчет для таблицы Sales:

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

У меня кошмар, когда я пытаюсь сделать что-то подобное с набором параметров Nullable @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 ]

8 голосов
/ 06 июня 2011

Я не думаю, что вам вообще нужен оператор 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)
   )    
6 голосов
/ 06 июня 2011

Если я вас правильно понял, вы хотите, чтобы три условия были NULL или проверены на:

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

Имейте в виду, что это вызывает сканирование таблицы, которое может быть не в ваших интересах.

3 голосов
/ 29 сентября 2011

Это должно работать и использовать любой индекс, если вы хотите использовать CASE:

SELECT * 
from Sales 
WHERE SaleDate BETWEEN @StartDate AND @EndDate 
AND SalesUserID = CASE WHEN @SalesUserID IS NULL THEN 
SalesUserID ELSE @SalesUserID END
2 голосов
/ 06 июня 2011

Я бы использовал динамически сгенерированный код при таких обстоятельствах:

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
2 голосов
/ 06 июня 2011

COALESCE() возвращает 1-й ненулевой аргумент, чтобы вы могли;

...
WHERE SaleDate BETWEEN @StartDate AND @EndDate
  AND SalesUserId = COALESCE(@SalesUserId, SalesUserId)
  AND SiteId = COALESCE(@SiteId, SiteId)
  AND BrandID = COALESCE(@BrandID, BrandId)
1 голос
/ 03 мая 2013

Попробуйте это:

SELECT * 
from Sales 
WHERE SaleDate BETWEEN @StartDate AND @EndDate 
AND SalesUserID = CASE WHEN @SalesUserID IS NULL THEN 
SalesUserID ELSE @SalesUserID END 
1 голос
/ 06 июня 2011

Обычно это работа для динамического SQl, если вам нужна производительность.

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

...