Подтвердить что ты не робот

Как использовать оператор case в функции скалярного значения в SQL?

Я хочу получить одно значение из функции, используя оператор case. Я попробовал следующее, но это не сработало:

CREATE FUNCTION [FATMS].[fnReturnByPeriod]
(

    @Period INT

)
RETURNS int
AS
BEGIN

    SELECT CASE @Period 
             when 1 then 1
             when @Period >1 and @Period <=7 then 1
             when @Period >7 and @Period <=30 then 1
             when @Period >30 and @Period<=90 then 1
             when @Period >90 and @Period <=180 then 1
             when @Period >180 and @Period <=360 then 1
             else 0
           END

    RETURN @Period
END
4b9b3361

Ответ 1

Существует два типа выражение CASE: простой и поиск. Вы должны выбрать один или другой - вы не можете использовать смесь обоих типов в одном выражении.

Попробуйте следующее:

SELECT CASE
    WHEN @Period = 1 THEN 1
    WHEN @Period > 1 AND @Period <= 7 THEN 2
    WHEN @Period > 7 AND @Period <= 30 then 3
    -- etc...
    ELSE 0
END

Кроме того, вам нужно присвоить результат чему-то, о чем уже указывали другие.

Ответ 2

Когда вы используете RETURN @Period, вы должны назначить значение @Period. В следующем примере показано, как структурировать ваш код, чтобы не было необходимости объявлять локальную переменную.

CREATE FUNCTION [FATMS].[fnReturnByPeriod]
(
    @Period INT
)
RETURNS INT
AS
BEGIN
    RETURN
        CASE 
            WHEN @Period = 1 THEN 1
            WHEN @Period > 1 AND @Period <=7 THEN 1
            WHEN @Period > 7 AND @Period <=30 THEN 1
            WHEN @Period > 30 AND @Period<=90 THEN 1
            WHEN @Period > 90 AND @Period <=180 THEN 1
            WHEN @Period > 180 AND @Period <=360 THEN 1
            ELSE 0
        END 
END

Ответ 3

Объявите вторую переменную, а затем установите это значение, потому что вы не перезагружаете @Period.

Например:

DECLARE @Output AS INT

SELECT @Output = CASE @Period 
                 WHEN 1 then 1     
                 WHEN @Period > 1 AND @Period <= 7 THEN 1      -- Should be 2 
                 WHEN @Period > 7 AND @Period <= 30 THEN 1     -- Should be 3
                 WHEN @Period > 30 AND @Period<= 90 THEN 1     -- Should be 4
                 WHEN @Period > 90 AND @Period <= 180 THEN 1   -- Should be 5  
                 WHEN @Period > 180 AND @Period <= 360 THEN 1  -- Should be 6   
                 ELSE 0 END;

RETURN @Output;

Я оставил его так, как я предполагаю, вы собираетесь изменить свои значения для каждого из этих операторов CASE.

Ответ 4

Вы не назначаете @Period нигде. Попробуйте с when @Period >1 and @Period <=7 then SET @Period = 1, а затем для всех остальных строк.

SQL не имеет неявных возвратов, поэтому вам всегда нужно установить переменные перед их возвратом.

Ответ 5

Как он "не работает"? Вызывает ли ошибка при попытке выполнить ее? Возвращает ли он неожиданный результат?

Сверху моей головы возникает несколько проблем:

Оператор case возвращает 1 во всех случаях.

Оператор case также объединяет два разных типа семантики CASE:

CASE @Period 
WHEN <condition> THEN <result>
WHEN <other condition> THEN <result>
ELSE <result>
END

или

CASE
WHEN @Period = <value> THEN <result>
WHEN @Period = <other value> THEN <result>
ELSE <result>
END

Вторая форма позволяет использовать несвязанные условия, тогда как первая может проверять только разные значения @Period.

Кроме того, вы возвращаете значение @Period, а не значение, генерируемое оператором CASE.

Ответ 6

Здесь основан подход на основе SET для записи вашей функции в SQL Server 2008

CREATE FUNCTION [FATMS].[fnReturnByPeriod]
(
    @Period INT
)
RETURNS int
AS
BEGIN
    return isnull((SELECT min(v)
    from (values
     (1,1),
     (7,2),
     (30,3),
     (90,4),
     (180,5),
     (360,6)) t(n,v)
    where n >= @Period and @period>0), 0)
END

Как вы его написали, все ветки CASE возвращают 1, поэтому вы можете использовать

return case when @period between 1 and 360 then 1 else 0 end