Розділіть дві колонки, але уникайте ділення на нуль

Я хочу зробити щось подібне з таблицею журналу підключення:

SELECT StartTime, EndTime, EventTime, SentBytes, SentObjects, \
    SentBytes/SentObjects AS bytes_per_object, \
    SentBytes/(EndTime - StartTime) AS bitrate, \
    (EndTime - StartTime) AS duration FROM [table];

Але в деяких подіях StartTime і EndTime можуть бути рівні (нульова тривалість), або SentObjects можуть бути нульовими. Тому вищенаведений запит дає поділ на нульову помилку. Як я можу переписати заяву, щоб отримати результат? Заміна ділянок на нуль з -1 - прекрасна.

Я маю на увазі щось подібне до цієї потрійної операції, але я не знаю, як її написати:

SELECT IFF(SentObjects > 0, SentBytes/SentObjects, -1) AS bytes_per_object FROM table;

SELECT .... WHERE SentObjects > 0 is not a desireable solution, as I want to see all the connections in one list.

Версія SQL Server 10_50

1

6 Відповіді

 select 1/nullif(0,0)

SELECT StartTime, EndTime, EventTime, SentBytes, SentObjects,  
    coalesce(SentBytes/NULLIF(SentObjects,0),-1) AS bytes_per_object,  
    coalesce(SentBytes/NULLIF((EndTime - StartTime),0),-1) AS bitrate,  
    (EndTime - StartTime) AS duration FROM [table] 

можна уникнути нуля, використовуючи наступну функцію

1
додано

Ви також можете скористатися виразом загальної таблиці (CTE): (неперевірений сценарій)

Ідея полягає в тому, щоб попередньо оцінити значення стовпців всередині CTE і використовувати оновлене значення в операторі select.

;With CTE 
AS(
    SELECT StartTime, EndTime, EventTime, 
           IIF(SentObjects > 0, SentBytes, 1) AS SentBytesUpdated, \
           IIF(SentObjects > 0, SentObjects, -1) AS SentObjectsUpdated , \
           SentBytes/(EndTime - StartTime) AS bitrate, \
           (EndTime - StartTime) AS Duration \
    FROM [Table]
)SELECT StartTime, EndTime, EventTime, \
    SentBytesUpdated/SentObjectsUpdated AS bytes_per_object, \
    bitrate \
    Duration \
FROM [CTE]
0
додано
SELECT StartTime, EndTime, EventTime, SentBytes, SentObjects,
    SentBytes/(case when isnull(SentObjects, 0) = 0 then -1 else SentObjects end) AS bytes_per_object,
    SentBytes/(case when isnull((EndTime - StartTime), 0) = 0 then -1 else (EndTime - StartTime)end) AS bitrate,
    (EndTime - StartTime) AS duration FROM [table];
0
додано

Ви можете використовувати CASE WHEN ... THEN ... ELSE ... END :

SELECT StartTime, EndTime, EventTime, SentBytes, SentObjects,
    CASE WHEN SentObjects = 0 THEN -1 ELSE SentBytes/SentObjects END AS bytes_per_object,
    CASE WHEN EndTime = StartTime THEN -1 ELSE SentBytes/(EndTime - StartTime) END AS bitrate,
    (EndTime - StartTime) AS duration
FROM [table];
0
додано
SELECT StartTime, EndTime, EventTime, SentBytes, SentObjects, \
    SentBytes/SentObjects AS bytes_per_object, \
    isNull(SentBytes/nullif((EndTime - StartTime), 0), -1) AS bitrate, \
    (EndTime - StartTime) AS duration FROM [table];
0
додано
CASE
WHEN SentObjects > 0 THEN SentBytes/SentObjects
ELSE -1
END AS bytes_per_object
0
додано