Как я могу предотвратить ошибки деления на ноль в хранимой процедуре?

Я попытался выполнить мою совершенно новую хранимую процедуру из обозревателя сервера, я получил:

Сообщение 8134, Уровень 16, Состояние 1, Процедура duckbilledPlatypi, Строка 13 Делить на ноль возникшей ошибки.

Вот линия (13):

@Week1End Week1End,

... и в большем контексте:

DECLARE 
@Week1End datetime,
@Week2begin datetime

Select Ind.Description,
    @BegDate  BegDate,
    @Week1End Week1End,
    @Week1End Week2Begin,
    @EndDate EndDate,

Для полного раскрытия / контекста, вот весь SP, как он теперь существует:

CREATE PROCEDURE [dbo].[duckbilledPlatypi]
    @Unit varchar(25),
    @BegDate datetime,
    @EndDate datetime
AS

DECLARE 
@Week1End datetime,
@Week2begin datetime

Select Ind.Description,
    @BegDate  BegDate,
    @Week1End Week1End,
    @Week1End Week2Begin,
    @EndDate EndDate,
    SUM(CASE WHEN Ind.InvoiceDate BETWEEN @BegDate AND @Week1End THEN Ind.QtyShipped ELSE 0 END) 
Week1Usage,
    SUM(CASE WHEN Ind.InvoiceDate BETWEEN @Week2Begin AND @EndDate THEN Ind.QtyShipped ELSE 0 END) 
Week2Usage,
    SUM(CASE WHEN Ind.InvoiceDate BETWEEN @BegDate AND @Week1End THEN Ind.Price ELSE 0 END) 
Week1Price,
    SUM(CASE WHEN Ind.InvoiceDate BETWEEN @Week2Begin AND @EndDate THEN Ind.Price ELSE 0 END) -
   SUM(CASE WHEN Ind.InvoiceDate BETWEEN @BegDate AND @Week1End THEN Ind.QtyShipped ELSE 0 END) 
UsageVariance,
    SUM(CASE WHEN Ind.InvoiceDate BETWEEN @Week2Begin AND @EndDate THEN Ind.QtyShipped ELSE 0 END)  -
    SUM(CASE WHEN Ind.InvoiceDate BETWEEN @BegDate AND @Week1End THEN Ind.Price ELSE 0 END) 
PriceVariance,
    (SUM(CASE WHEN Ind.InvoiceDate BETWEEN @Week2Begin AND @EndDate THEN Ind.QtyShipped ELSE 0 
END)  -
    SUM(CASE WHEN Ind.InvoiceDate BETWEEN @BegDate AND @Week1End THEN Ind.Price ELSE 0 END) )
    / SUM(CASE WHEN Ind.InvoiceDate BETWEEN @BegDate AND @Week1End THEN Ind.Price ELSE 0 END) 
PercentageOfPriceVariance
    From    InvoiceDetail Ind
    Where   Ind.Unit = @Unit
    AND Ind.InvoiceDate BETWEEN @BegDate AND @EndDate
    Group By Ind.Description

Я предполагаю, что @Week1End Week1End терпит неудачу, потому что ему не присваивается значение, и поэтому он является нулевым. Я не знаю, должен ли я сделать что-то вроде этого, чтобы предотвратить 0s/null:

DECLARE 
@Week1End datetime = BegDate + 6;
@Week2begin datetime = BegDate + 7;

... или что-то вроде этого:

Select Ind.Description,
    @BegDate  BegDate,
    @Week1End BegDate+6,
    @Week2Begin BegDate+7,
    @EndDate EndDate,

... или что-то совсем другое.

Как вы, вероятно, можете сказать, я не знаю, как на самом деле нужно выполнять математику. Какие даты действительно должны быть:

Week1Begin is the "BegDate" the user provided as a parameter
Week1End needs to be six days after Week1Begin
Week2Begin needs to be seven days after Week1Begin
Week2End is the "EndDate" the user provided as a parameter

например, если пользователь ввел "27.12.2015" для BegDate и "06.01.2016" для EndDate, эти значения должны быть:

Week1Begin = 12/27/2015
Week1End = 1/2/2016
Week2Begin = 1/3/2016
Week2End = 1/6/2016 (week2 is only a four-day week in this case, due to what the user entered)

Что я должен сделать, чтобы убедиться, что здесь нет делений на нули?

1 ответ

Решение

Вы могли бы использовать NULLIF:

   (SUM(CASE WHEN Ind.InvoiceDate BETWEEN @Week2Begin AND @EndDate THEN Ind.QtyShipped ELSE 0 
END)  -
    SUM(CASE WHEN Ind.InvoiceDate BETWEEN @BegDate AND @Week1End THEN Ind.Price ELSE 0 END) )
    / NULLIF(SUM(CASE WHEN Ind.InvoiceDate BETWEEN @BegDate AND @Week1End THEN Ind.Price ELSE 0 END),0) 
PercentageOfPriceVariance

Так что, когда делитель 0 результат будет NULL, Если вам нужно особое значение для этого случая, добавьте COALESCE:

COALESCE(exp1 / NULLIF(exp2, 0), special_value) AS result

LiveDemo

Другие вопросы по тегам