Разделите два столбца, но избегайте деления на ноль

Я хочу сделать что-то подобное с таблицей журналов соединений:

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
добавлено

Вы также можете использовать Common Table Expression (CTE): (Untested script)

Идея состоит в том, чтобы предварительно оценить значения столбцов внутри 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
добавлено
SqlCom.ru - Стиль жизни SQL
SqlCom.ru - Стиль жизни SQL
908 участник(ов)

Правила чата - https://t.me/sqlcom/88269 @sqlcom - основной канал (только MS SQL) @sql_ninja - второй канал (SQL вопросы начального уровня и свободное общение) @Gopnegbot - Викторина по SQL Server (наберите в привате /quiz). Предложения в @sql_ninja

SQL_Ninja
SQL_Ninja
340 участник(ов)

Правила чата - https://t.me/sqlcom/88269 @sqlcom - основной канал (только SQL) @sql_ninja - второй канал (SQL вопросы начального уровня и свободное общение) @Gopnegbot - Викторина по SQL Server (наберите в привате /quiz)