powered by simpleCommunicator - 2.0.59     © 2026 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / Firebird, InterBase [игнор отключен] [закрыт для гостей] / with execute block
25 сообщений из 38, страница 1 из 2
with execute block
    #38772896
Здравствуйте!

Искал решение одного вопроса и наткнулся на сообщение Влада Хорсуна (правильно перевёл?) о том, что он хотел внести предложение использовать конструкцию execute block в CTE. Однако больше об этом что-то ничего нигде не упоминалось (гугл не нашел).
Вот интересно: в данном направлении есть какие-нибудь движения? Или решили что это пижонство?
...
Рейтинг: 0 / 0
with execute block
    #38772949
Фотография Симонов Денис
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Артемий Соболев,

не видел такого. А для чего это потребовалось. Может есть другие способы решения. Например в тройке внутри EXECUTE BLOCK разрешено в секции DECLARE объявлять локальные подпроцедуры и подфункции.

P.S. В 12 оракле что типа такого есть


Код: plsql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
WITH
  FUNCTION with_function(p_id IN NUMBER) RETURN NUMBER IS
  BEGIN
    RETURN p_id;
  END;
SELECT with_function(id)
FROM   t1
WHERE  rownum = 1
/

WITH_FUNCTION(ID)
-----------------
                1

SQL>
...
Рейтинг: 0 / 0
with execute block
    #38772982
hvlad
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Артемий Соболевв данном направлении есть какие-нибудь движения?Пока нет
...
Рейтинг: 0 / 0
with execute block
    #38773210
Требовалось сделать выборку из таблиц на основе другой таблицы, и к результату применить группировку с агрегацией. Один из вариантов - дополнительная ХП. Не хотелось её рисовать, но, видимо, никуда не денешься, придёться ;)
...
Рейтинг: 0 / 0
with execute block
    #38773235
Dimitry Sibiryakov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Говнодизайн БД detected.
...
Рейтинг: 0 / 0
with execute block
    #38943259
Возвращаяст к говнодизайну (переделывать никто не даст).

Этот проект - журнал ремонтов оборудования на заводе. Есть таблица ремонтов. Она активно использует справочники и немного уникальной информации, как-то дата проведения ремонта, тип работ и другие мелочи (поля - указатели на соответствующие записи в справочниках). Так-же есть пара вспомогательных таблиц на орбите, данные которых соотносятся с таблицей ремонтов в отношении многие ко многим. Справочник оборудования выполнен в виде дерева вида: ID_оборудования, ID_предка, название_оборудования, другие_мелочи.

Нужно получить аггрегированную информацию (sum, count) из этих орбитальных таблиц причем с ограничением по конкретному оборудованию и конкретному пользователю.

При атаке "в лоб" - вывод данных за месяц по одному параметру производится от 1 минуты до 4, при этом в месяц происходит примерно 700-1000 ремонтов. Это неприемлимо долго. Выяснил, что поиск по оборудованию от корня к листьям в данном случае не подходит. Обратный поиск заметно быстрее, но тогда возникает проблема с аггрегацией данных в рамках одного запроса/одной ХП.

Текущее решение состоит из ХП выдающей промежуточный результат, и SQL запроса, собирающий итог из данных возвращаемых этой ХП. В ХП имеется 2 вложенных for select.

Вопрос: можно ли не прибегая к внешним запросам или ХП, в рамках одной процедуры получить агрегированные данные?
...
Рейтинг: 0 / 0
with execute block
    #38943265
Фотография Симонов Денис
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Артемий Соболев,

ты запросик сюда кинь, может чего и подскажут. Необязательно свой оригинальный запрос. Можно что попроще для примера. В тройке можно попробовать через оконные функции
...
Рейтинг: 0 / 0
with execute block
    #38943285
Переработанный вариант общего итога (без орбитальных таблиц)

Хранимка:
Код: plsql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
begin
 v_time1 = iif(i_time_1 is null, '01.01.2000', i_time_1);
 v_time2 = iif(i_time_2 is null, cast(dateadd(day, 1, current_date) as timestamp_info), i_time_2);

 for select et.device_id, sum(coalesce(et.dend - et.dbegin, 0)), count(et.event_id)
       from events_tbl et join users_ref ur using(user_id) join get_shop_childs(:i_dep_id) ds on ur.dep_id = ds.o_dep_id
      where et.dbegin >= :v_time1
        and et.dbegin < :v_time2
      group by 1
       into :v_dev_id, :o_sum_raw_time, :o_count_events
 do
 begin
  o_dev_id = null;
  with recursive dev_table as (
       select dev_id, parent_dev_id, dev_type, dev_name
         from devices_ref
        where dev_id = :v_dev_id
       union all
       select dr.dev_id, dr.parent_dev_id, dr.dev_type, dr.dev_name
         from devices_ref dr join dev_table dt on dr.dev_id = dt.parent_dev_id
  )
  select d.dev_id, trim(decode(d.dev_type, 1, '', dtr.dev_type_name) || ' ' || d.dev_name)
    from dev_table d join dev_type_ref dtr on d.dev_type = dtr.dev_type_id
   where parent_dev_id = :i_device_id
    into :o_dev_id, :o_dev_name;

  if (o_dev_id is not null) then
   suspend;
 end
end



ну и запрос соответствующий
Код: sql
1.
2.
3.
select o_dev_id, o_dev_name, sum(o_sum_raw_time), sum(o_count_events)
from get_device_summary(входные значения ограничения)
group by 1, 2



Хранимка (долгий вариант) для одной из орбитальных таблиц:
Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
begin
 if (i_time_1 is null) then
  v_time_1 = '01.01.2000';
 else
  v_time_1 = i_time_1;

 if (i_time_2 is null) then
  v_time_2 = dateadd(day, 1, current_date);
 else
  v_time_2 = i_time_2;

 for select zr.zip_id, zr.zip_name, zr.sap_n, uz.zip_sum
       from zip_ref zr, (select z.zip_id, sum(z.zip_count) zip_sum
                           from use_zip z join events_tbl et using(event_id)
                                join users_ref ur using(user_id) join get_shop_childs(:i_dep_id) ds
                                on ur.dep_id = ds.o_dep_id
                                join (with recursive dev_table as (
                                            select dev_id
                                              from devices_ref
                                             where parent_dev_id = :o_dev_id
                                            union all
                                            select dr1.dev_id
                                             from devices_ref dr1 join dev_table dt on dr1.parent_dev_id = dt.dev_id)
                                      select dev_id
                                        from dev_table) gde on et.device_id = gde.o_dev_elem_id
                                       where et.dbegin >= :v_time_1 and et.dbegin < :v_time_2
                         group by 1) uz
      where zr.zip_id = uz.zip_id
       into :o_zip_id, :o_zip_name, :o_sap_no, :o_count
 do
  suspend;
end



сломал уже голову, как можно это переделать чтобы быстро работало.
...
Рейтинг: 0 / 0
with execute block
    #38943366
Фотография Симонов Денис
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Артемий Соболев,

кто тебе мешает считать суммы в самом цикле for select, а потом просто лишний suspend воткнуть

типа такого

Код: plsql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
sum_quantity = 0;
for select id, name, sum(quantity)
     from ....
     group by 1, 2
     into  id, name, quantity
do begin
  sum_quantity = sum_quantity + quantity; 
  suspend;
end
id = null;
name = 'Итого';
quantity = sum_quantity;
suspend;
...
Рейтинг: 0 / 0
with execute block
    #38943377
Симонов Денис,

да собственно, ничего не мешает. Была такая мысль. Вот только не помню, почему не реализовал (отказался). Это наверно от усталости. Надо отпуск брать и в горы уходить на недели две...
...
Рейтинг: 0 / 0
with execute block
    #38943402
Вспомнил почему!

o_dev_id и v_dev_id они разные и o_dev_id не идут подряд. Значит надо организовывать что-то вроде массива, что не есть хорошо. Сервер сам как-то это считает (наверно сортирует результат). Вот и как мне организовать эту сортировку? Там разброс может равновероятным на всем отрезке. И с повторами само собой. В общем не получится внутри второго цикла это считать ибо сортировку не сделать
...
Рейтинг: 0 / 0
with execute block
    #38943413
Фотография Симонов Денис
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Артемий Соболев,

можно сначала загнать предварительные результаты в GTT и затем считать по ней

или в трёшке использовать SUM(PARTITION BY <нужные поля группировки>)
...
Рейтинг: 0 / 0
with execute block
    #38943444
Симонов Денис,

трёшка пока не рассматривается совсем (бета, и переносить проект - отдельный вопрос, возможно получиться и дизайн сменить), а вот насчет GTT - что-то не получается. Мож чего не правильно делал?
Можно пример, стопудово рабочий?
...
Рейтинг: 0 / 0
with execute block
    #38943458
Фотография Симонов Денис
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Артемий Соболев,

а в чём проблема. Создаёшь GTT нужной структуры. GTT создаётся заранее а не динамически в ХП.

Затем делаем так

INSERT INTO MY_GTT(<поля>)
SELECT ... // твой сложный запрос

и далее

SELECT ... FROM MY_GTT // с нужными обработками

тут главный плюс MY_GTT можно соединять много раз и при этом сложный запрос не перевыполняется. Т.е. в данном случае мы используем GTT в качестве материализации того сложного запроса.
...
Рейтинг: 0 / 0
with execute block
    #38943470
Симонов Денис,

А эта GTT создается одна на всех пользюков, или для каждого своя?
...
Рейтинг: 0 / 0
with execute block
    #38943482
Фотография DarkMaster
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Артемий Соболев,

Одна.
...
Рейтинг: 0 / 0
with execute block
    #38943510
Ivan_Pisarevsky
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Артемий СоболевА эта GTT создается одна на всех пользюков, или для каждого своя?Метаданные одни на всех, но данные каждые видит строго свои (своей транзакции или своего коннекта, как настроишь).
...
Рейтинг: 0 / 0
with execute block
    #38943623
hvlad
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Артемий СоболевВот и как мне организовать эту сортировку?Ты удивишься, но - с ORDER BY
...
Рейтинг: 0 / 0
with execute block
    #38943653
hvladАртемий СоболевВот и как мне организовать эту сортировку?Ты удивишься, но - с ORDER BY
Спасибо, К.О.! Вот может ко всему подскажете, как организовать сортировку на вложенном for select для всего набора? (по входным данным из первого for select)
...
Рейтинг: 0 / 0
with execute block
    #38943698
hvlad
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Артемий СоболевВот может ко всему подскажетеЕсли бы в твоём описании можно было хоть что-то понять (меньше чем за полдня и без 100 грамм) - то может и подсказал бы
...
Рейтинг: 0 / 0
with execute block
    #38943727
hvladАртемий СоболевВот может ко всему подскажетеЕсли бы в твоём описании можно было хоть что-то понять (меньше чем за полдня и без 100 грамм) - то может и подсказал бы
Прошу прощения за сумбур в описании. в сообщении 17552771 в первом скрипте видны два цикла. Допустим в первом цикле выходят значения 78, 67, 98, 45... во вложенном втором цикле КАЖДОМУ значению соответствует ровно 1 значение, пусть будет например 1, 7, 14, 7 соответственно. мне нужно сделать сортировку (группирование) значений из внешнего цикла по значениям внутреннего цикла. Как видно, 7 встречается 2 раза, соответственно на выходе должно быть три строки 1, 7, 14. Для семерки должны состоятся суммирования. Вот не выходя за пределы одной ХП и не используя вспомогательную ХП каким образом сделать подсчеты, ну или сортировку для подсчетов вручную.
В свете GTT получается достаточно приемлемый вариант. Только надо озаботиться очисткой и другими безобразиями перед использованием. Но тогда ещё вопрос: кто и когда должен озаботиться удалением этой таблицы?
...
Рейтинг: 0 / 0
with execute block
    #38943735
Dimitry Sibiryakov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Артемий Соболевещё вопрос: кто и когда должен озаботиться удалением этой таблицы?

Никто и никогда. Почитай уже доку.
Posted via ActualForum NNTP Server 1.5
...
Рейтинг: 0 / 0
with execute block
    #38943752
Фотография DarkMaster
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Артемий СоболевВ свете GTT получается достаточно приемлемый вариант. Только надо озаботиться очисткой и другими безобразиями перед использованием. Но тогда ещё вопрос: кто и когда должен озаботиться удалением этой таблицы?

Ты когда создаешь GTT - указываешь, когда данные в ней должны быть убиты. А дальше сервер сам все сделает.
...
Рейтинг: 0 / 0
with execute block
    #38943952
Ivan_Pisarevsky
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Артемий СоболевТолько надо озаботиться очисткой и другими безобразиями перед использованием.Доку почитай уже. При старте транзации (или коннекта) таблица всегда чистая.
...
Рейтинг: 0 / 0
with execute block
    #38944143
Dorin Marcoci
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Немножко отошли от топика в сторону GTT, но всетаки "with execute block (params)" это будет мощная штука, если будет.
Незнаю если у Артемий прямо "Говнодизайн БД detected" но вот бы мне очень помогла такая конструкция, пока нету collateral joins.
Вот для топика http://www.sql.ru/forum/1152604/mozhno-li-vypolnit-odnim-zaprosom оптимально не обошелся без доп процедуры.
...
Рейтинг: 0 / 0
25 сообщений из 38, страница 1 из 2
Форумы / Firebird, InterBase [игнор отключен] [закрыт для гостей] / with execute block
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


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