Гость
Map
Форумы / Informix [игнор отключен] [закрыт для гостей] / Простой способ определения наличия ссылок? / 8 сообщений из 8, страница 1 из 1
01.08.2014, 12:12
    #38710693
NetSpider
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Простой способ определения наличия ссылок?
Добрый день, форумчане!
Возникла задачка сделать выборку записей, на которые ни кто (ни какая другая таблица) не ссылается...
сначала, хотел сделать как обычно:
Код: sql
1.
2.
3.
select * from main_tab where key_id not in (select key_id from ref_tab1);
-- или
select * from main_tab m where not exists (select r.key_id from ref_tab1 r where r.key_id = m.key_id);



проблема только в том, что таблиц, подобных ref_tab1 несколько десятков.

Вопрос: есть-ли какой-то более хитрый (оптимальный) способ, сделать подобную выборку, способ доступный для использования в простом запросе.

БД: IBM Informix Dynamic Server Version 11.50.FC9
...
Рейтинг: 0 / 0
02.08.2014, 15:01
    #38711380
victor16
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Простой способ определения наличия ссылок?
NetSpiderсделать выборку записей, на которые ни кто (ни какая другая таблица) не ссылается... таблиц, подобных ref_tab1 несколько десятков...
другого способа нет, кроме как обойти все эти detail-таблицы
Код: sql
1.
2.
3.
4.
5.
select * from main_tab 
where key_id not in (select key_id from ref_tab1)
   and key_id not in (select key_id from ref_tab2)
   and key_id not in (select key_id from ref_tab3)
... /* повторяем для всех detail-таблиц */ ...


или
Код: sql
1.
2.
3.
4.
5.
select * from main_tab m 
where not exists (select r.key_id from ref_tab1 r where r.key_id = m.key_id)
  and not exists (select r.key_id from ref_tab2 r where r.key_id = m.key_id)
  and not exists (select r.key_id from ref_tab3 r where r.key_id = m.key_id)
... /* повторяем для всех detail-таблиц */ ...



Если никакой другой задачи не стоит, кроме как выбрать - этого селекта будет достаточно.
Другой вопрос - как определить эти несколько десятков detail-таблиц, которые ссылаются на эту таблицу. Можно начать примерно с такого запроса:
Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
SELECT master.tabname mastertable,
       "->",
       slave.tabname slavetable,
" and not exists (select 1 from " || trim(master.tabname) || 
" where " || trim(get_join_str(sysreferences.constrid)) || ");"
FROM sysreferences,
       systables master,
       sysconstraints masterconstr,
       systables slave,
       sysconstraints slaveconstr,
       outer sysconstraints slaveprim
 WHERE slaveconstr.constrid = sysreferences.constrid
and lower(master.tabname) = lower("<tabname>")  
   AND master.tabid = sysreferences.ptabid
   AND masterconstr.constrid = sysreferences.primary
   AND slave.tabid = slaveconstr.tabid
   AND masterconstr.tabid = master.tabid
   AND slaveprim.tabid = slave.tabid
   AND slaveprim.constrtype = "P"
ORDER BY 1,2;


get_join_str - это функция, возвращающая строку соединения
Код: 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.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
EXECUTE PROCEDURE ifx_allow_newline('t');
create procedure get_join_str(p_constrid INT)
 returning lvarchar;
 define p_join_str lvarchar;
 define p_master_idxname lvarchar;
 define p_master_tabname lvarchar;
 define p_master_tabid integer;
 define p_slave_idxname lvarchar;
 define p_slave_tabname lvarchar;
 define p_slave_tabid integer;
 define p_idxcolno integer;
 define p_master_colname lvarchar;
 define p_master_colno lvarchar;
 define p_slave_colname lvarchar;
 define p_slave_colno lvarchar;

 SELECT masterconstr.idxname, master.tabname, master.tabid, slaveconstr.idxname, slave.tabname, slave.tabid
   INTO p_master_idxname, p_master_tabname, p_master_tabid, p_slave_idxname, p_slave_tabname, p_slave_tabid
   FROM sysreferences,
        systables master,
        sysconstraints masterconstr,
        systables slave,
        sysconstraints slaveconstr
  WHERE slaveconstr.constrid = sysreferences.constrid
    AND sysreferences.constrid = p_constrid
    AND master.tabid = sysreferences.ptabid
    AND masterconstr.constrid = sysreferences.primary
    AND slave.tabid = slaveconstr.tabid
    AND masterconstr.tabid = master.tabid;

 LET p_join_str = "";
 LET p_idxcolno = 0;
 LOOP
     SELECT ikeyextractcolno(indexkeys, p_idxcolno) INTO p_master_colno FROM sysindices WHERE sysindices.idxname == p_master_idxname;
     SELECT ikeyextractcolno(indexkeys, p_idxcolno) INTO p_slave_colno FROM sysindices WHERE sysindices.idxname == p_slave_idxname;
     IF p_master_colno == 0 OR p_slave_colno == 0 THEN
        EXIT LOOP;
     END IF;
     LET p_idxcolno = p_idxcolno + 1;
     SELECT colname INTO p_master_colname FROM syscolumns
      WHERE tabid = p_master_tabid AND colno = p_master_colno;
     SELECT colname INTO p_slave_colname FROM syscolumns
      WHERE tabid = p_slave_tabid AND colno = p_slave_colno;
     IF LENGTH(p_join_str) > 0 THEN
        LET p_join_str = trim(p_join_str) || "
AND ";
     END IF;
     LET p_join_str = trim(p_join_str) || " " || trim(p_master_tabname) || "." || trim(p_master_colname) ||
                                    " = " || trim(p_slave_tabname) || "." || trim(p_slave_colname);
 END LOOP;

 LET p_join_str = trim(p_join_str);
 return p_join_str;
end procedure;
EXECUTE PROCEDURE ifx_allow_newline('f');
...
Рейтинг: 0 / 0
04.08.2014, 11:59
    #38711958
NetSpider
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Простой способ определения наличия ссылок?
Большое спасибо за ответ!
Обошелся exists'ами, благо список ссылающихся таблиц определить трудностей не составило.
Только выполнять пришлось не весь запрос разом (чтобы не ждать его выполнения пол дня), а разделить на неск. частей прогоняя через вр. таблицы.

Отдельное спасибо за процедурку!))
...
Рейтинг: 0 / 0
04.08.2014, 13:05
    #38712053
Журавлев Денис
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Простой способ определения наличия ссылок?
select * from main_tab a left outer join second_t b on a.f=b.f left outer join third_t c on a.f=c.f where b.f is null and c.f is null

a b c
1 1 1
2 2 2
3 3
4
...
Рейтинг: 0 / 0
05.08.2014, 13:03
    #38712959
NetSpider
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Простой способ определения наличия ссылок?
Журавлев Денисselect * from main_tab a left outer join second_t b on a.f=b.f left outer join third_t c on a.f=c.f where b.f is null and c.f is null

a b c
1 1 1
2 2 2
3 3
4

хм... тоже интересный вариант, попробовал на неск. таблицах - даже вроде как быстрее)) Спасибо за подсказку!

Перейдя на информикс совсем стал забывать про *join*, хотя не думаю, что тут виноват информикс))
...
Рейтинг: 0 / 0
05.08.2014, 15:02
    #38713136
Журавлев Денис
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Простой способ определения наличия ссылок?
NetSpiderПерейдя на информикс совсем стал забывать про *join*, хотя не думаю, что тут виноват информикс))
я предлагал один запросом заджойнить все таблицы, чтобы в main_tab зайти один раз.

по идее в идеальном сферическом оптимизаторе это ничем не отличается от варианта

select * from main_tab m where
not exists (select r.key_id from ref_tab1 r where r.key_id = m.key_id) and
not exists (select r.key_id from ref_tab2 r where r.key_id = m.key_id) and
not exists (select r.key_id from ref_tab3 r where r.key_id = m.key_id) and
not exists (select r.key_id from ref_tab4 r where r.key_id = m.key_id) and
...
Рейтинг: 0 / 0
05.08.2014, 15:05
    #38713139
Журавлев Денис
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Простой способ определения наличия ссылок?
NetSpider
Перейдя на информикс совсем стал забывать про *join*, хотя не думаю, что тут виноват информикс))
кажись "родной" синтаксис информикса не позволяет пометить предикат post-join или pre-join поэтому без анси-ситаксиса не обойтись
...
Рейтинг: 0 / 0
13.08.2014, 12:21
    #38719197
NetSpider
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Простой способ определения наличия ссылок?
Журавлев ДенисNetSpiderПерейдя на информикс совсем стал забывать про *join*, хотя не думаю, что тут виноват информикс))
кажись "родной" синтаксис информикса не позволяет пометить предикат post-join или pre-join поэтому без анси-ситаксиса не обойтись

Используя Informix-Extension Outer Joins, результата, подобного ANSI-join, добиться не удалось, что в принципе, не удивительно...
Так что - да, либо без join'ов либо ansi

Если я Вас правильно понимаю))
...
Рейтинг: 0 / 0
Форумы / Informix [игнор отключен] [закрыт для гостей] / Простой способ определения наличия ссылок? / 8 сообщений из 8, страница 1 из 1
Целевая тема:
Создать новую тему:
Автор:
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


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