SQL-сервер Ошибка деления на ноль

В любом случае у меня есть запрос в следующей форме

select 
(select count(*) from sometable where somecritiea) / ((select count(*) from sometable where somecritiea) + 0.000001) 
from sometable

Я делю результат подсчета на результат подсчета, поэтому нули не являются проблемой.

Когда я запускаю это, я получаю «Обнаружена ошибка деления на ноль». Обратите внимание на +0,000001 в делителе.

Если я вставлю перечислитель (?) и делитель в новую таблицу, а затем сделаю тот же расчет, он будет работать, как и ожидалось.

select 
(select count(*) from sometable where somecritiea) a/ ((select count(*) from sometable where somecritiea) + 0.000001) b
into testtable
from sometable

выберите a/b из тестовой таблицы

это возвращает ожидаемые результаты без ошибок.

Если я побегу

select * from testtable where b = 0
i get 0 records as expected.

Я действительно теряюсь здесь, это 5-минутная работа, которая превратилась в 5-часовой беспорядок.

я тоже пробовал

select *
((select count(*) from sometable where somecritiea) + 0.000001) divisor
from sometable
where divisor = 0

Это не возвращает никаких записей.


person user2201214    schedule 23.03.2013    source источник
comment
Ну, я попробовал select (select count(*) from sometable where 1=2)/( select (select count(*) from sometable where 1=2) + 0.000001) и не получил ошибку. Так что, если честно, я понятия не имею, что происходит... Но вы могли бы попробовать мой запрос, просто чтобы посмотреть, не проблема ли это?   -  person DigCamara    schedule 23.03.2013


Ответы (3)


Честно говоря, я тоже не смог воспроизвести вашу проблему, но это должно работать независимо.

WITH Divisor AS (select count(*)*1.0 BotCnt from sys.procedures),
    Dividend AS (select count(*)*1.0 TopCnt from sys.tables )
SELECT 
    CASE WHEN BotCnt = 0 THEN 0 ELSE TopCnt/BotCnt END,
    *
FROM sys.objects
CROSS JOIN Divisor
CROSS JOIN Dividend

Обратите внимание на *1.0. То есть преобразовать количество в десятичное число. Вы могли бы использовать явное преобразование так же легко. CROSS JOIN работает только потому, что два CTE представляют собой одну строку. В противном случае используйте INNER JOIN с предложением ON.

person Kenneth Fisher    schedule 23.03.2013

Это самое близкое, что я мог бы быстро воспроизвести ваш сценарий, и он отлично работает; возвращает 0.0000000:

with sometable as (
  select * from ( values 
    (0)
  ) sometable(value)
)
select 
  (select count(*) from sometable where value <> 0 )
/ 
( (select count(*) from sometable where value <> 0 ) + 0.000001 ) 
from sometable
person Pieter Geerkens    schedule 23.03.2013

Попробуйте NULLIF на своем делителе

select 
(select count(*) from sometable where somecritiea) / NULLIF((select count(*) from sometable     where somecritiea) + 0.000001), 0) from sometable

Это вернет NULL вместо деления на 0 всякий раз, когда знаменатель равен 0. Если вам не нужен NULL, а какой-то другой ответ по умолчанию (например, 9), используйте ISNULL для всего запроса, чтобы преобразовать его обратно в 0.

person Kanwal Sarwara    schedule 23.03.2013