powered by simpleCommunicator - 2.0.61     © 2026 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / Firebird, InterBase [игнор отключен] [закрыт для гостей] / Избежать ветвления (IF) в ХП
14 сообщений из 14, страница 1 из 1
Избежать ветвления (IF) в ХП
    #38778012
fedorov2012
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Возникла такая задача, есть хранимая процедура на вход которой передается параметр. Если он не нулевой то должна приджоиниться еще одна таблица, т.е. подобно этому:

Код: 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.
create or alter procedure sp_my(ASessionID integer = 0)
returns (
 f1 integer,
 f2 integer,
...
as
begin
 
 if (ASessionID = 0) then
 begin
   for select t2.*, t3.*
   from table1 t1
          join table2 t2 on (t2.fid=t1.fid and t2.is_visible = 1)
          left join table2 t3 on t3.uid=t2.uid
   into ...
   do begin
      --код А
   end
 end
 else
 begin
   for select t2.*, t3.*
   from table1 t1          
          join table2 t2 on (t2.fid=t1.fid and t2.is_visible = 1)
          join table_session ts on (ts.session_id=:ASessionID and t2.fid=ts.id)
          left join table2 t3 on t3.uid=t2.uid
   into ...
   do begin
      --код А
   end
 end  
end



А хотелось бы избежать ветвления т.к. код А один и тот же и длинный, можно ли как-то записать так:
Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
create or alter procedure sp_my(ASessionID integer = 0)
returns (
 f1 integer,
 f2 integer,
...
as
begin

   for select t2.*, t3.*
   from table1 t1
          join table2 t2 on (t2.fid=t1.fid and t2.is_visible = 1)
          join table_session ts on (:ASessionID=0) or (ts.session_id=:ASessionID and t2.fid=ts.id) -- т.е. если ASessionID = 0, то просто игнорируем table_session 
          left join table2 t3 on t3.uid=t2.uid
   into ...
   do begin
      --код А
   end
...
Рейтинг: 0 / 0
Избежать ветвления (IF) в ХП
    #38778017
m7m
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
fedorov2012
А хотелось бы избежать ветвления т.к. код А один и тот же и длинный, можно ли как-то записать так:
Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
create or alter procedure sp_my(ASessionID integer = 0)
returns (
 f1 integer,
 f2 integer,
...
as
begin

   for select t2.*, t3.*
   from table1 t1
          join table2 t2 on (t2.fid=t1.fid and t2.is_visible = 1)
          join table_session ts on (:ASessionID=0) or (ts.session_id=:ASessionID and t2.fid=ts.id) -- т.е. если ASessionID = 0, то просто игнорируем table_session 
          left join table2 t3 on t3.uid=t2.uid
   into ...
   do begin
      --код А
   end


а что попробовал и ругается при компиляции?????
чего-то мне не верится в такое
зы. однако как мне кажется при таком условии table_session будет сканировать натуралом
ззы. как по мне то вот так лучше
Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
begin

   for select t2.*, t3.*
   from table1 t1
          join table2 t2 on (t2.fid=t1.fid and t2.is_visible = 1)
--          join table_session ts on (:ASessionID=0) or (ts.session_id=:ASessionID and t2.fid=ts.id) -- т.е. если ASessionID = 0, то просто игнорируем table_session 
          left join table2 t3 on t3.uid=t2.uid
   into ...
   do begin
     if (ASessionID<>0  or
       (exists(select * from table_session ts where (ts.session_id=:ASessionID and t2.fid=:ts_id))) then
      begin
          --код А
      end
   end
...
Рейтинг: 0 / 0
Избежать ветвления (IF) в ХП
    #38778029
fedorov2012
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
автор m7m , а что попробовал и ругается при компиляции?????
Не ругается, процедура возвращает пустоту при ASessionID = 0
...
Рейтинг: 0 / 0
Избежать ветвления (IF) в ХП
    #38778059
Фотография kdv
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
fedorov2012Если он не нулевой то должна приджоиниться еще одна таблица
не выйдет. Если такой запрос select нельзя написать в DSQL, то нельзя и в PSQL.
...
Рейтинг: 0 / 0
Избежать ветвления (IF) в ХП
    #38778146
m7m
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
fedorov2012автор m7m , а что попробовал и ругается при компиляции?????
Не ругается, процедура возвращает пустоту при ASessionID = 0
ну если возвращает пустоту то мне не хватает знаний
я чего-то думал что такой финт пройдет вполне нормально
значит буду штудировать джойны
...
Рейтинг: 0 / 0
Избежать ветвления (IF) в ХП
    #38778206
m7m
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
fedorov2012автор m7m , а что попробовал и ругается при компиляции?????
Не ругается, процедура возвращает пустоту при ASessionID = 0

Посмотрел, почитал, попробовал и пришел к выводу что если
этот запрос
Код: sql
1.
2.
3.
4.
5.
 select t2.*, t3.*
   from table1 t1
          join table2 t2 on (t2.fid=t1.fid and t2.is_visible = 1)
          join table_session ts on (:ASessionID=0) or (ts.session_id=:ASessionID and t2.fid=ts.id) -- т.е. если ASessionID = 0, то просто игнорируем table_session 
          left join table2 t3 on t3.uid=t2.uid



при ASessionID <> 0 возвращает записи
то тем более он возвращает записи при ASessionID = 0
вот только во втором случае количество записей будет гораздо больше чем в первом
ибо по сути во втором случае мы имеем джойн без условия
а это наверное не совсем то что ожидалось
запрос дающий ожидаемый (ну тот что я бы ожидал) результат будет вот такой

Код: sql
1.
2.
3.
4.
5.
6.
 select t2.*, t3.*
   from table1 t1
          join table2 t2 on (t2.fid=t1.fid and t2.is_visible = 1)
--          join table_session ts on (:ASessionID=0) or (ts.session_id=:ASessionID and t2.fid=ts.id) -- т.е. если ASessionID = 0, то просто игнорируем table_session 
          left join table2 t3 on t3.uid=t2.uid
    where exists(select * from table_session ts where (:ASessionID=0) or (ts.session_id=:ASessionID and t2.fid=ts.id) )



зы. Это по сути то-же самое что и предыдущее предложение с проверкой условия внутри цикла
...
Рейтинг: 0 / 0
Избежать ветвления (IF) в ХП
    #38778238
fedorov2012
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
m7m, select во where это select на каждую результирующую запись from'a - это тормоза
пока сделал через IF
...
Рейтинг: 0 / 0
Избежать ветвления (IF) в ХП
    #38778312
m7m
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
fedorov2012m7m, select во where это select на каждую результирующую запись from'a - это тормоза
пока сделал через IF
Вопрос был про "А хотелось бы избежать ветвления т.к. код А один и тот же и длинный, можно ли как-то записать так:"
зы. ну я ошибся, вместо
Код: sql
1.
2.
     if (ASessionID<>0  or
       (exists(select * from table_session ts where (ts.session_id=:ASessionID and t2.fid=:ts_id))) then


надо
Код: sql
1.
2.
     if (ASessionID=0  or
       (exists(select * from table_session ts where (ts.session_id=:ASessionID and t2.fid=:ts_id))) then

и если это
Код: sql
1.
2.
3.
4.
5.
6.
7.
  do begin
     if (ASessionID=0  or
       (exists(select * from table_session ts where (ts.session_id=:ASessionID and t2.fid=:ts_id))) then
      begin
          --код А
      end
   end


тормозит, то тогда
Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
   do begin
     sw=1;
     if (ASessionID<>0) then
       if (not exists(select * from table_session ts where (ts.session_id=:ASessionID and t2.fid=:ts_id))) then sw=0;
     if (sw=1)
      begin
          --код А
      end
   end
...
Рейтинг: 0 / 0
Избежать ветвления (IF) в ХП
    #38778674
Fr0sT-Brutal
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
А если так:
Код: 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.
33.
34.
35.
36.
37.
38.
39.
40.
41.
CREATE OR ALTER PROCEDURE Ibe$Testcur (
  Cond INTEGER)
RETURNS (
  Id   INTEGER,
  Name VARCHAR(200))
AS
  DECLARE Cur1 CURSOR FOR (
      SELECT Foo_id, Foo_Name
        FROM Foo);
  DECLARE Cur2 CURSOR FOR (
      SELECT Bar_id, Bar_Name
        FROM Bar);
BEGIN
  IF (:Cond = 0) THEN
    OPEN Cur1;
  ELSE
    OPEN Cur2;

  WHILE (1 = 1) DO
  BEGIN
    IF (:Cond = 0) THEN
      FETCH Cur1
        INTO :Id, :Name;
    ELSE
      FETCH Cur2
        INTO :Id, :Name;

    IF (ROW_COUNT = 0) THEN
      LEAVE;

   ... do something ...

    SUSPEND;
  END

  IF (:Cond = 0) THEN
    CLOSE Cur1;
  ELSE
    CLOSE Cur2;

END
...
Рейтинг: 0 / 0
Избежать ветвления (IF) в ХП
    #38779069
fedorov2012
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
А так на FB можно?
...
Рейтинг: 0 / 0
Избежать ветвления (IF) в ХП
    #38779082
m7m
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
fedorov2012А так на FB можно?
DECLARE
FETCH
...
Рейтинг: 0 / 0
Избежать ветвления (IF) в ХП
    #38779096
fedorov2012
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
m7m, ok - не юзал ранее

что касается запроса выше от Fr0sT-Brutal - мне кажется, проще обычным IF, но в любом случае спасибо
...
Рейтинг: 0 / 0
Избежать ветвления (IF) в ХП
    #38779107
Fr0sT-Brutal
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Проверял на 2.5, полностью рабочий вариант.
Как знаешь, конечно, но если вдруг ты когда-нибудь что-то изменишь в "Коде А"-1 и забудешь это сделать в "Коде А"-2 и через полгода это вылезет мистическим трудновылавливаемым багом - вспомни этот день xD
...
Рейтинг: 0 / 0
Избежать ветвления (IF) в ХП
    #38779133
fedorov2012
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
спасибо
...
Рейтинг: 0 / 0
14 сообщений из 14, страница 1 из 1
Форумы / Firebird, InterBase [игнор отключен] [закрыт для гостей] / Избежать ветвления (IF) в ХП
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


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