LEFT JOIN по ХП с ORDER BY

Запросы, планы, оптимизация запросов, ...

Модераторы: kdv, CyberMax

Ответить
Monk
Сообщения: 38
Зарегистрирован: 30 май 2006, 12:33

LEFT JOIN по ХП с ORDER BY

Сообщение Monk » 09 ноя 2006, 15:03

Есть запрос, вида

Код: Выделить всё

SELECT
 T1.*,
 P1.SUM1_OUT,
 ...
 P1.SUMn_OUT 
FROM TABLE1 T1
LEFT JOIN PPOCEDURE1(T1.ID) P1 ON (P1.ID_OUT = T1.ID)
WHERE
 фильтр по T1
ORDER BY
 T1.ID
где процедура

Код: Выделить всё

CREATE PROCEDURE PPOCEDURE1(
    ID_IN INTEGER)
RETURNS (
    ID_OUT INTEGER,
    SUM1_OUT NUMERIC(18,2),
    ...
    SUMn_OUT NUMERIC(18,2))
AS
BEGIN
 ID_OUT = :ID_IN;
 
 if (:ID_IN is not NULL) then
  begin
   какой то код, считающий выходные параметры
  end

 SUSPEND;
END
В том случае, когда в селекте в качестве входного параметра передается NULL, я получаю ошибку 'Overflow occured.....convertion error from string "" "". '

Если я убираю ORDER BY из запроса то получаю набор данных

Это моих кривых ручек дело или особенности Interbase 7.51 sp1?

CyberMax
Заслуженный разработчик
Сообщения: 638
Зарегистрирован: 31 янв 2006, 09:05

Сообщение CyberMax » 10 ноя 2006, 10:58

Х. Борри про FB пишет, что выходные параметры ХП обязательно должны быть проинициализированы, иначе последствия непресказуемы. Будем считать, что это актуально и для IB 7.
В твоем случае, если ID_IN не NULL, нет инициализации SUM1_OUT ... SUMn_OUT.
P.S. Нет такого типа, как NUMERIC(18,2). Максимум - 18 цифр (NUMERIC(16,2)). В один прекрасный момент может получиться неприятность...

kdv
Forum Admin
Сообщения: 6595
Зарегистрирован: 25 окт 2004, 18:07

Сообщение kdv » 10 ноя 2006, 11:25

P.S. Нет такого типа, как NUMERIC(18,2). Максимум - 18 цифр (NUMERIC(16,2)). В один прекрасный момент может получиться неприятность...
ошибка.

numeric(precision, scale) - где
precision - макс кол-во цифр в числе, вообще
scale - масштаб. то есть * 10^scale при сохранении, и div 10^scale при считывании.

поэтому, разумеется, 18 знаков это НЕ precision + scale. это именно precision. scale может быть тоже 18, при этом хранить можно будет числа вида 0.1-18.

Monk
Сообщения: 38
Зарегистрирован: 30 май 2006, 12:33

Сообщение Monk » 10 ноя 2006, 12:00

CyberMax писал(а):....нет инициализации SUM1_OUT ... SUMn_OUT.
P.S. Нет такого типа, как NUMERIC(18,2).....
Изменил на

Код: Выделить всё

CREATE PROCEDURE PPOCEDURE1(
    ID_IN INTEGER)
RETURNS (
    ID_OUT INTEGER,
    SUM1_OUT NUMERIC(16,2),
    ...
    SUMn_OUT NUMERIC(16,2))
AS
BEGIN
 ID_OUT = :ID_IN;
 SUM1_OUT = NULL;
 ...
 SUMn_OUT = NULL;
 
 if (:ID_IN is not NULL) then
  begin
   какой то код, считающий выходные параметры
  end

 SUSPEND;
END
Рестартнул сервер

Запустил запрос снова - и снова такая же песня
Причем ошибка, как показал эксперимент, возникает только в том случае, когда строка с NULL в таблице Т1 является последней (вновь добавленной), если сразу после нее добавить что то с NOT NULL то запрос с ORDER BY выполняется корректно.

ЗЫ
Без инициализации поведение запроса такое же как с инициализацией, т.ч. не в ней дело.

CyberMax
Заслуженный разработчик
Сообщения: 638
Зарегистрирован: 31 янв 2006, 09:05

Сообщение CyberMax » 11 ноя 2006, 03:22

kdv писал(а):ошибка.
Да, ошибся.

Monk
Сообщения: 38
Зарегистрирован: 30 май 2006, 12:33

Сообщение Monk » 11 ноя 2006, 11:47

Не считайте меня слишком назойливым, но все же

Почему без ORDER BY все работает, а с ним не всегда, можно конечно же не писать LEFT JOIN по ХП, а написать несколько SELECTов по ХП внутри SELECTа по таблицы, но слишком не красивый код, да и производительность боюсь пострадает?

Или использование ORDER BY в конструкции с LEFT JOIN по ХП с возможными NULL это из разряда не документированных возможностей?

ЗЫ
Беда в том что такой запрос в отчете (сортировка нужна для использования Группировок в ФастРепорте) использую и не могу воспользоваться локальной фильтрацией - приходится данные в эксель выгружать и делать там сводные таблицы.

Karp
Сообщения: 41
Зарегистрирован: 30 апр 2005, 16:30

Re: LEFT JOIN по ХП с ORDER BY

Сообщение Karp » 13 ноя 2006, 12:13

Monk писал(а): В том случае, когда в селекте в качестве входного параметра передается NULL, я получаю ошибку

Код: Выделить всё

ID_OUT = COALESCE(:ID_IN, 0);
if (:ID_IN > 0) then 
  .....

Monk
Сообщения: 38
Зарегистрирован: 30 май 2006, 12:33

Re: LEFT JOIN по ХП с ORDER BY

Сообщение Monk » 13 ноя 2006, 19:33

Karp писал(а):

Код: Выделить всё

ID_OUT = COALESCE(:ID_IN, 0);
if (:ID_IN > 0) then 
  .....
Попробовал - результат тот же. Без ORDER работает, а с сортировкой ошибка.
ЗЫ. Все индексы прибиты (кроме PK).

Karp
Сообщения: 41
Зарегистрирован: 30 апр 2005, 16:30

Re: LEFT JOIN по ХП с ORDER BY

Сообщение Karp » 14 ноя 2006, 10:41

Monk писал(а): Попробовал - результат тот же. Без ORDER работает, а с сортировкой ошибка.
ЗЫ. Все индексы прибиты (кроме PK).
пиши Борландам тогда

я проверял на Yaffil-890 (таблица с ХП по left join) - сортировка по полю с null работает

Monk
Сообщения: 38
Зарегистрирован: 30 май 2006, 12:33

Re: LEFT JOIN по ХП с ORDER BY

Сообщение Monk » 14 ноя 2006, 11:32

Karp писал(а): пиши Борландам тогда
я проверял на Yaffil-890 (таблица с ХП по left join) - сортировка по полю с null работает
Думаю придеться писать, только сначала нужно понять комбинацию данных при которых такая связка не работает. Если я создаю тестовую таблицу (с 2мя полями - ID и с нулом поле) и к ней ХП джойню то все работает. Но на реальных данных (по моей таблице) все рушится. Причем если я свою таблицу выгружаю в дамп (скрипт с INSERTтами) и добавляю его в новую базу, то история такая же.
Реальная таблица представляет собой спецификацию коммерческих предложений с древовидной архитектурой (ID, PARENT, код товара, кол-ва, цены и пр..... - там где "код товара" = NULL - это ветка), к которой идет JOIN с суммой, посчитанной исходя из себестоимости и процентом доходности (в зависимости от ранга пользователя возвращается или NULL или реальные цифры, или комбинация NULL и реальных цифр).
Даже если процедуру переписать и выкинуть всю аналитику (в конструкции после if инициировать переменные в 0, например), убрать все индексы, убрать все JOINы, возвращающие из справочников Модель, Наименование модели, Единицу измерения товара и пр.., оставивь лишь SELECT по спецификации с JOIN по ХП, то часть запросов с ORDER выполняется, а часть нет (зависит от наполняемости данными, причем не рабочую зависимость я понять не могу - если я добавил только ветки в спецификацию и не добавлял товары (одни строки с NULLами) то JOIN выполняется, если добавляю товар, то зависит куда я его добавлю), причем часть данных возвращается (т.е иногда пару строк получу, иногда всю спецификацию, кроме последней, вновь добавленной строки), при этом вижу ошибку Overflow occured.....convertion error from string "" "", где в кавычках то ничего, цифра 1, то цифра 4... что за цифры и откуда я не понимаю, нет таких в таблице.

Oleg Loa
Сообщения: 11
Зарегистрирован: 31 окт 2004, 18:24

Сообщение Oleg Loa » 15 ноя 2006, 11:40

Это всё очень интересно, но ответ один. Делай тест, выявляющий ошибку, и отправляй его борланду.

Правда вероятность получить в следующем SP исправление - крайне низка, борланду явно не до того сейчас.

Ответить