powered by simpleCommunicator - 2.0.59     © 2026 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / Microsoft SQL Server [игнор отключен] [закрыт для гостей] / Два одинаковых запроса - различный результат !!!
21 сообщений из 21, страница 1 из 1
Два одинаковых запроса - различный результат !!!
    #32013978
Vadim
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
MSSQL7 sp3

Ниже представлены два ОДИНАКОВЫХ запроса, только вот результаты у них совершенно разные... Почему? И как этого избежать, так как запросы намного сложнее... это так сказать строгая "выжимка".

1 Запрос:--------------------------------------------
select * from
(
select * from
(select * from MyTable where
from_x-to_x != 0
) bb
where
(from_y - to_y)/(from_x-to_x) != 0
) aa
1 Результат:-----------------------------------------
Divide by zero error encountered.

2 Запрос:--------------------------------------------
select * from
(select * from MyTable where
from_x-to_x != 0
) bb
where
(from_y - to_y)/(from_x-to_x) != 0
2 Результат:-----------------------------------------
Набор из 623 записей...
...
Рейтинг: 0 / 0
Два одинаковых запроса - различный результат !!!
    #32013980
Vadim
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Черт ошибся когда копировал из клипборда:
P.S. Надеюсь различия видны не вооруженным взглядом...
Запрос 1
select * from
(
select * from
(select * from MyTable where
from_x-to_x != 0
) b1
where
(from_y - to_y)/(from_x-to_x) != 0
) a1

Запрос 2
select * from
(select * from MyTable where
from_x-to_x != 0
) b1
where
(from_y - to_y)/(from_x-to_x) != 0
...
Рейтинг: 0 / 0
Два одинаковых запроса - различный результат !!!
    #32013981
Vadim
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
) нет не ошибся, это UltraBoard TAB'ы съел.
...
Рейтинг: 0 / 0
Два одинаковых запроса - различный результат !!!
    #32014012
wlad
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
А from_x, to_x, from_y, to_y - какого типа?
...
Рейтинг: 0 / 0
Два одинаковых запроса - различный результат !!!
    #32014035
Вадим, скорее всего ошибка случается на какой-то одной записи.
Постарайся ее найти.
Затем ксли можно пришли скрипт, который воспроизводит ошибку, т.е.

create table...
insert .. values ...

select ...

Да, и еще - какая у тебя версия сервера и SP -
select @@version
...
Рейтинг: 0 / 0
Два одинаковых запроса - различный результат !!!
    #32014036
SQL7 SP3 - увидел. Хорошо. Посторайся сделать скрипт воспроизведения...
...
Рейтинг: 0 / 0
Два одинаковых запроса - различный результат !!!
    #32014064
Vadim
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
После долгих мучений сам нашел
Дело было в том, что для MSSQL7 почему то, почему? Эти выражения не эквивалентны:

where from_x <> to_x
и
where from_x - to_x != 0

В первом случае всё заработало без ошибочно... Но, я так и не понял механизм, происшедшего Придется просто принять на заметку и пользоваться. Мне кажется, всё дело в оптимизации запроса MSSQL'ем, соответсвенно как бы ее отключить? Может есть какой способ?

Но, всё равно, мне не ясно - запросы одинаковые ПОЧЕМУ ответы разные???

TO_X NUMERIC(6,2) NOT NULL

P.S. А конференции типа swrus-mssql-sql нет? Именно по хранимым процедурам и sql-ям... а не по администрированию?

TO Алексей Ельцов: не сюда же это постить пиши мне на vav@newmail.ru перейдем в приват. А почему ты отвечал в 6:45 утра это у тебя работа так рано начинается? 8(
...
Рейтинг: 0 / 0
Два одинаковых запроса - различный результат !!!
    #32014098
Фотография Garya
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Типичные проблемы при работе с числами с плавающей точкой. Кстати, в некоторых источниках эти числа справедливо называют приблизительными числами. Сравнение этих чисел на точное равенство (или неравенство) является стратегической ошибкой. Сравнение с 0 (которое имеет тип int) приводит к неявному преобразованию нуля к Float. При преобразовании могут возникнуть ошибки преобразования и ноль превратится не в ноль, а в очень маленькое число. Лучше сравнивать не на точное равенство, а на неравенство (например, where abs(X-Y)<1.0E-3.
По первоначально поставленному вопросу могу сказать, что кроме тривиального деления на ноль при решении данной задачи могут возникать и другие ошибки. В частности, переполнение разрядной сетки (при делении очень большого числа на очень маленькое), потеря значимости (при делении очень маленького числа на очень большое).
И еще. Реакция на подобные ошибки устанавливается опцией SET ARITH_ABORT ON/OFF (см BOL).
...
Рейтинг: 0 / 0
Два одинаковых запроса - различный результат !!!
    #32014106
> TO Алексей Ельцов: не сюда же это постить

Мне кажеся, что сюда - даже лучше. Я думаю, каждому кто следит за дискуссией будет интересно посмотреть на воспроизводимую ошибку. Тогда уже будет понятно в чем действительно дело.
(Например, ты написал, что TO_X - numeric. А второй важный компонент - FROM_X - остался за кадром. Если-бы был скрипт воспроизведения, то было бы меньше вопросов и больше ответов)

> А почему ты отвечал в 6:45 утра это у тебя работа так рано начинается? 8(

У меня просто другой часовой пояс
...
Рейтинг: 0 / 0
Два одинаковых запроса - различный результат !!!
    #32014110
Павел
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
2 Vadim
Я никогда не был в Южносахалинске, но достоверно знаю что и там используют MSSQL. А между тем когда москвичи после тяжелого трудового дня пьют пиво, на Сахалине уже начинается новый тяжелый трудовой день. Вот такая у нас большая страна. Имейте это ввиду.
...
Рейтинг: 0 / 0
Два одинаковых запроса - различный результат !!!
    #32014446
Vadim
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Хмм. Алексей Вы правы, конечно насчет скрипта, но как бы проблема решилась. А подготовить скрипт это долго и потом я думаю все равно не выйдет ничего путного, а была не была )
Насчет FROM естественно он такой же как и TO, поэтому я про него и не написал

CREATE TABLE MyTABLE (
NAME_REC NUMERIC(6,0) NOT NULL,
TO_X NUMERIC(6,2) NOT NULL,
FROM_X NUMERIC(6,2) NOT NULL,
PRIMARY KEY (NAME_REC)
);

А как сделать автоматический скрипт с данными, не перечислять же руками Insert Insert Insert ...

Здесь еще кто-то слушает?
...
Рейтинг: 0 / 0
Два одинаковых запроса - различный результат !!!
    #32014505
maximF
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Конечно, с помощью insert'ов. Если результаты запросов различны, то достаточно наполнить таблицы-участники парой записей
...
Рейтинг: 0 / 0
Два одинаковых запроса - различный результат !!!
    #32014595
Vadim
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Напоминаю, что все это происходит в MSSQL7.0 sp2. В MSSQL6.5 ВСЁ РАБОТАЕТ!

Ну что ж, каково же было мое удивление, когда я таки написал для вас этот скрипт! Я упростил до минимума и так и не понял, что это издевательство Микрософта? Если обратите внимание, тип данных я заменил на NUMERIC(6,0) и сделал всего 3 поля...

3-4 записи это необходимость, так как если убрать их, кажется, что все работает - просто выдается сообщение об ошибке... ан нет если добавить - видно, что в результат выводиться _только_ первая запись...

P.S. Эх всю жизнь натыкаюсь на такого рода грабли, быть бы мне бетатестером у того же Микрософта...

CREATE PROCEDURE tests AS

CREATE TABLE #MyTABLE (
NAME_REC NUMERIC(6,0) NOT NULL,
TO_X NUMERIC(6,0) NOT NULL,
FROM_X NUMERIC(6,0) NOT NULL,
PRIMARY KEY (NAME_REC)
);

insert into #MyTable
(name_rec,to_x,from_x)
values (1, 78, 56)

insert into #MyTable
(name_rec,to_x,from_x)
values (2, 79, 79)

insert into #MyTable
(name_rec,to_x,from_x)
values (3, 58, 69)

insert into #MyTable
(name_rec,to_x,from_x)
values (4, 57, 69)

print '__________________________________________________________'
print 'View all records:'
print '__________________________________________________________'
select * from #MyTable

print '__________________________________________________________'
print 'Result: All is good !'
print '__________________________________________________________'

select * from
(
select * from #MyTable where
from_x-to_x != 0
) b1
where
(from_x + to_x)/(from_x-to_x) != 0

print '__________________________________________________________'
print 'Result: "Divide by zero"?!!'
print '__________________________________________________________'

select * from
(
select * from
(
select * from #MyTable where
from_x-to_x != 0
) b1
where
(from_x + to_x)/(from_x-to_x) != 0
) a1

print '__________________________________________________________'
print 'Result: "Divide by zero"?!! Again !'
print '__________________________________________________________'

select * from
(
select * from
(
select * from #MyTable c1 where
c1.from_x != c1.to_x
) b1
where
(b1.from_x + b1.to_x)/(b1.from_x-b1.to_x) != 0
) a1

print 'Copyright by Vadim Pristavko vav@newmail.ru 2001'

drop table #MyTable

return
...
Рейтинг: 0 / 0
Два одинаковых запроса - различный результат !!!
    #32014698
Michael+Hopgarden
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
IMHO оптимизатор пытается преобразовать Ваши выкрутасы к виду select * from #MyTable where ... and ... or ... etc., а, отнюдь, не к соединению подзапросов и, тем более, не к последовательному их выполнению. Отсюда и деление на ноль в условиях, что вполне закономерно.
...
Рейтинг: 0 / 0
Два одинаковых запроса - различный результат !!!
    #32014751
Vadim
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Конечно, "оптимизатор" что-то там пытается сделать. А называть это выкрутасами?!! Мне, что же теперь работу с базой данных свести до одного select?! Да я уж лучше тогда в 6.5 вернусь, но это бред, такого быть не может. Запрос намного сложнее, как я говорил с самого начала. Здесь написан скрипт, который приводит к отказу _нормально_ постороенного запроса, причем прошу заметить, построенного по всем правилам ANSI может их уже кто отменил, чтобы нам удобнее было?! Вопрос остается ОТКРЫТЫМ! И ответа на него нет. Возможно, есть какая-то директива - отключения/включения этого оптимизатора, на время выполнения моего "выкрутасного" запроса?

P.S. Неделю не мог достучаться до форума
...
Рейтинг: 0 / 0
Два одинаковых запроса - различный результат !!!
    #32014995
Очень классный пример
Убираем в нем первый INSERT и получаем деление на 0 во всех трех селектах
Так что вопрос скорее ставится с точностью наоборот - почему "нормальный" SELECT не выдает ошибку?
...
Рейтинг: 0 / 0
Два одинаковых запроса - различный результат !!!
    #32014996
Ситуация следующая - в SQL 7.0 первый SELECT отрабатывает - остальные нет.
в SQL 2000 первый SELECT тоже не отрабатывает.

Мое объяснение

приведенный селект оптимизируется в один SELECT, где WHERE
(to_x-from_x>0 or to_x-from_x<0) and ((to_x+from_x)/(to_x+from_x)>0 or (to_x+from_x)/(to_x+from_x)>0)
Если почитать документацию - там сказано - что ВСЕ условия OR и AND после WHERE обрабатываются сервером ОДНОВРЕМЕННО

Как результат - в SQL 7.0 SELECT отработал из-за ПЛОХОЙ оптимизации

Теперь о граблях - использование вложенных селектов может приводить к непредсказуемым результатам. Единственный выход - разбиение на несколько запросов с использованием временных таблиц (в 2000 таблицу можно декларировать в процедуре как переменную)

В то же время - использование промежуточных таблиц приведет к существенному утяжелению запроса. и как следствие к снижению производительности и увеличению потребляемых ресурсов.

Какие у народа будут мысли по этому поводу?
...
Рейтинг: 0 / 0
Два одинаковых запроса - различный результат !!!
    #32015030
Glory
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Эээ, может просто добавит перед выполнением

SET ARITHABORT OFF
go
SET ANSI_WARNINGS OFF
go

тогда по крайней мере выполнение запроса не будет прерываться
...
Рейтинг: 0 / 0
Два одинаковых запроса - различный результат !!!
    #32015032
SerCh
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Народ! А если подумать немного прежде чем делать запрос?
Зачем нагружать сервер еще каким-то делением, если:
а) проверка на неравность нулю делителя сделана;
6) частное будет =0 <-> делимое =0;
То есть вместо (from_y - to_y)/(from_x-to_x) != 0
почему бы просто не оставить проверку (from_y - to_y)!=0 ?
По-моему, этого будет достаточно, и накопленная погрешность будет значительно меньше. А?
...
Рейтинг: 0 / 0
Два одинаковых запроса - различный результат !!!
    #32015191
Vadim
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Да, что-то с Интернетом у нас стало... то на форум пробиться не мог, то у нас какие-то грабли
Кстати, а нельзя подписаться на форум и получать его в виде News или E-Mail по типу subscribe.ru или yahoo groups?

Касательно моего запроса, вставив в начало:
SET ANSI_WARNINGS OFF
SET ARITHIGNORE ON
и в конец
SET ANSI_WARNINGS ON
SET ARITHIGNORE OFF
(Она надо ли? По идее эта установка должна работать только на время и в теле моего запроса? Drop для таблицы точно не надо, но так мне спокойнее )
все заработало.
Выход, пока, я вижу именно в создании временной таблицы/таблиц

TO SerCh : я с самого начала сказал, что это _упрощенный_ вариант запроса, можно добавить значение to_x = -69 ... если бы все запросы были простые... вначале да, insert update select а потом select select select select select....
...
Рейтинг: 0 / 0
Два одинаковых запроса - различный результат !!!
    #32015218
Оптимизатор запросов преобразует твой запрос так, что деление на ноль оказывается в начале. Неприятно, конечно.
Но с другой стороны, если посмотреть на выигрыш в скорости, который достигается для большого количества других запросов, то я согласен с таким неудобством.

> Выход, пока, я вижу именно в создании временной таблицы/таблиц

Я тоже сделал такой вывод. В 2000 возможно переменная типа таблица будет быстрее.
Кстати, в 2000 все 3 из запроса из скрипта воспроизведения дают деление на ноль.
...
Рейтинг: 0 / 0
21 сообщений из 21, страница 1 из 1
Форумы / Microsoft SQL Server [игнор отключен] [закрыт для гостей] / Два одинаковых запроса - различный результат !!!
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]