powered by simpleCommunicator - 2.0.61     © 2026 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / Oracle [игнор отключен] [закрыт для гостей] / Запрос с ЛГБТ связью
7 сообщений из 7, страница 1 из 1
Запрос с ЛГБТ связью
    #39681783
HOME_X
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Доброго дня господа !

Подскажите возможно ли соорудить запрос
(не могу сформулировать условие для связи)

К T1 присоединяем (left join) ОДНУ ЗАПИСЬ из T2 образуя результат отраженный в T3

Логика связи
Часть первая - первое минимально значение от списка значений T1.F1>T2.F2 (Min(T2.F2))
Часть вторая - запись из T2, которая НЕ ВОСТРЕБОВАНА !!!! предидущей записью T1

Пример
T1.F1=10 - Min запись из списка > T2.F2 (12,14,20,24,25,26,28,29) Выбрать 12 (запись T2.F2= 12 не востребована ранее)
T1.F1=15 - Min запись из списка > T2.F2 ( 20,24,25,26,28,29) Выбрать 20 (запись 20 НЕ востребована записью T1.F1=10)
T1.F1=16 - Min запись из списка > T2.F2 ( 20,24,25,26,28,29) Выбрать 24 (запись 20 УЖЕ востребована записью T1.F1=15)
T1.F1=18 - Min запись из списка > T2.F2 ( 20,24,25,26,28,29) Выбрать 25 (запись 20|24 УЖЕ востребов записью T1.F1=15|16)
T1.F1=27 - Min запись из списка > T2.F2 ( 28,29) Выбрать 28(запись 28 НЕ востребована ранее )
T1.F1=30 - Min запись из списка > T2.F2 ( <список пуст>) Выбрать Null

Код: 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.
with T1(F1) as (select 10 from DUAL union all
                select 15 from DUAL union all
                select 16 from DUAL union all
                select 18 from DUAL union all
                select 27 from DUAL union all
                select 30 from DUAL
               ),
     T2(F2) as (select  8 from DUAL union all
                select  9 from DUAL union all
                select 12 from DUAL union all
                select 14 from DUAL union all
                select 20 from DUAL union all
                select 24 from DUAL union all
                select 25 from DUAL union all
                select 26 from DUAL union all 
                select 28 from DUAL union all
                select 29 from DUAL 
               ),
  T3(F1,F2) as (select 10,12   from DUAL union all
                select 15,20   from DUAL union all
                select 16,24   from DUAL union all
                select 18,25   from DUAL union all
                select 27,28   from DUAL union all
                select 30,Null from DUAL
               )
select *
  from T3



Заранее благодарен !
...
Рейтинг: 0 / 0
Запрос с ЛГБТ связью
    #39681785
HOME_X
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
HOME_X,

Подправляю, ошибся !
Логика связи
Часть первая - первое минимально значение от списка значений T1.F1 < T2.F2 (Min(T2.F2))
Часть вторая - запись из T2, которая НЕ ВОСТРЕБОВАНА !!!! предидущей записью T1
...
Рейтинг: 0 / 0
Запрос с ЛГБТ связью
    #39681805
Фотография andrey_anonymous
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Вообще это вариация алгоритма sort-merge join.
Проще всего, наверное, на pl/sql:

Код: 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.
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.
56.
57.
58.
59.
60.
61.
62.
63.
64.
drop table dropme_t1 purge;
drop table dropme_t2 purge;

create or replace package lgbt as 
 type lgbt_rec is record (f1 number, f2 number);
 type lgbt_tab is table of lgbt_rec;
function lgbt_join(ct1 sys_refcursor, ct2 sys_refcursor) return lgbt_tab pipelined;  
end;
/

create or replace package body lgbt as 
    function lgbt_join(ct1 sys_refcursor, ct2 sys_refcursor) return lgbt_tab pipelined
    is
      l_ret_rec lgbt_rec;
    begin
      loop
        fetch ct1 into l_ret_rec.f1;
        exit when ct1%notfound;    
        loop
          fetch ct2 into l_ret_rec.f2;
            if ct2%notfound then 
              l_ret_rec.f2 := null;
              exit;
            end if;
          exit when l_ret_rec.f1 < l_ret_rec.f2;
        end loop;    
        pipe row (l_ret_rec);
      end loop;
      if ct1%isopen then close ct1; end if;
      if ct2%isopen then close ct2; end if;
      return;
    end;  
end;
/

create table dropme_t1 as 
with T1(F1) as (select 10 from DUAL union all
                select 15 from DUAL union all
                select 16 from DUAL union all
                select 18 from DUAL union all
                select 27 from DUAL union all
                select 30 from DUAL
               )
select * from t1
;
create table dropme_t2 as 
with T2(F2) as (select  8 from DUAL union all
                select  9 from DUAL union all
                select 12 from DUAL union all
                select 14 from DUAL union all
                select 20 from DUAL union all
                select 24 from DUAL union all
                select 25 from DUAL union all
                select 26 from DUAL union all 
                select 28 from DUAL union all
                select 29 from DUAL 
               )
select * from t2               
;               

select * from table(lgbt.lgbt_join( cursor(select f1 from dropme_t1 order by f1)
                                  , cursor(select f2 from dropme_t2 order by f2)
))
;
...
Рейтинг: 0 / 0
Запрос с ЛГБТ связью
    #39681807
Фотография dbms_photoshop
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
HOME_X,

Интересует SQL-баловство или PL/SQL алгоритм?
Код: 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.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
SQL> with T1(F1) as (select 10 from DUAL union all
  2                  select 15 from DUAL union all
  3                  select 16 from DUAL union all
  4                  select 18 from DUAL union all
  5                  select 27 from DUAL union all
  6                  select 30 from DUAL
  7                 ),
  8       T2(F2) as (select  8 from DUAL union all
  9                  select  9 from DUAL union all
 10                  select 12 from DUAL union all
 11                  select 14 from DUAL union all
 12                  select 20 from DUAL union all
 13                  select 24 from DUAL union all
 14                  select 25 from DUAL union all
 15                  select 26 from DUAL union all
 16                  select 28 from DUAL union all
 17                  select 29 from DUAL
 18                 ),
 19    T3(F1,F2) as (select 10,12   from DUAL union all
 20                  select 15,20   from DUAL union all
 21                  select 16,24   from DUAL union all
 22                  select 18,25   from DUAL union all
 23                  select 27,28   from DUAL union all
 24                  select 30,Null from DUAL
 25                 ),
 26  t01(rn, f1) as
 27   (select row_number() over(order by f1) rn, f1 from t1),
 28  rec(idx, id1, id2) as
 29   (select 1 idx, t01.f1, (select min(f2) from t2 where f2 > f1)
 30      from t01
 31     where rn = 1
 32    union all
 33    select t01.rn,
 34           t01.f1,
 35           (select min(f2) from t2 where f2 > greatest(rec.id2, t01.f1))
 36      from t01
 37      join rec
 38        on rec.idx + 1 = t01.rn)
 39  select id1 f2, id2 f2 from rec;

        F2         F2
---------- ----------
        10         12
        15         20
        16         24
        18         25
        27         28
        30

6 rows selected.



Здесь минус то, что при каждом вычислении рекурсивного члена выполняется полное сканирование T1 и полное сканирование T2.
Впрочем, если создать индексы (и в t1 ходить через cross apply/lateral), то этого можно избежать.

На PL/SQL решается линейным проходом обеих таблиц без всяких индексов.
...
Рейтинг: 0 / 0
Запрос с ЛГБТ связью
    #39681810
Фотография dbms_photoshop
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
dbms_photoshopесли создать индексы (и в t1 ходить через cross apply/lateral), то этого можно избежать

Код: plsql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
create table t1(f1, constraint pk_t1 primary key(f1)) as
               (select 10 from DUAL union all
                select 15 from DUAL union all
                select 16 from DUAL union all
                select 18 from DUAL union all
                select 27 from DUAL union all
                select 30 from DUAL
               );
               
create table t2(f2, constraint pk_t2 primary key(f2)) as
               (select  8 from DUAL union all
                select  9 from DUAL union all
                select 12 from DUAL union all
                select 14 from DUAL union all
                select 20 from DUAL union all
                select 24 from DUAL union all
                select 25 from DUAL union all
                select 26 from DUAL union all 
                select 28 from DUAL union all
                select 29 from DUAL 
               );



Код: plsql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
SQL> with rec(id1, id2) as
  2   (select t1.f1, (select min(f2) from t2 where f2 > f1)
  3      from (select min(t1.f1) f1 from t1) t1
  4    union all
  5    select t1.f1, (select min(f2) from t2 where f2 > greatest(rec.id2, t1.f1))
  6      from rec, lateral (select min(f1) f1 from t1 where t1.f1 > rec.id1) t1
  7     where rec.id1 is not null)
  8  select id1 f2, id2 f2 from rec where id1 is not null;

        F2         F2
---------- ----------
        10         12
        15         20
        16         24
        18         25
        27         28
        30

6 rows selected.
...
Рейтинг: 0 / 0
Запрос с ЛГБТ связью
    #39681828
Фотография Elic
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Интересно, а нужно ли Джуджу именно такое попадание в поисковики благодаря таким тупым совпенкам?
...
Рейтинг: 0 / 0
Запрос с ЛГБТ связью
    #39681876
Фотография -2-
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Код: plsql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
select f1, f2
from (
   select s, f f1, lead(f) over(partition by g, case s when 1 then s1 else s2 end order by f) f2
   from (
      select +1 s, f1 f from t1
      union all
      select -1 s, f2 f from t2
   ) match_recognize (
      order by f
      measures
         count(case when s=+1 then 1 end) s1,
         count(case when s=-1 then 1 end) s2,
         match_number() as g
      all rows per match
      pattern (run+)
      define   run as sum(s) >= 0 -- reset running count
   )
)
where s = 1
order by f1;     
...
Рейтинг: 0 / 0
7 сообщений из 7, страница 1 из 1
Форумы / Oracle [игнор отключен] [закрыт для гостей] / Запрос с ЛГБТ связью
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


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