powered by simpleCommunicator - 2.0.51     © 2025 Programmizd 02
Форумы / Oracle [игнор отключен] [закрыт для гостей] / Фрактальный RCTE
7 сообщений из 7, страница 1 из 1
Фрактальный RCTE
    #40020929
НеофитSQL
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Пытаюсь рекурсивно сгенерить фрактал
0-1
0-.5, 0.5-1
0-.25, .25-.5, .5-.75, .75-1
И т.д.

Каждый уровень делит предыдущие отрезки пополам, удваивая их число.

Код: plsql
1.
2.
3.
4.
5.
Cte fractal (a,b) as (
select 0,1 from dual union all
Select a, (a+b)/2 from cte union all
Select (a+b)/2, b from cte
)



Такой код недозволен ораклом, т.к в рекурсивных cte можно только один union all.

Я могу решить, сделав джойн с таблицей из двух строк, но это выглядит коряво.

Есть какие-то другие решения, для размножения строк внутри RCTE?
...
Рейтинг: 0 / 0
Фрактальный RCTE
    #40020935
НеофитSQL
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Код: plsql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
With duo (r) as (
Select 0 from dual union all
Select 1 from dual
),
Cte (a,b) as (
select 0,1 from dual union all
Select 
  decode(r, 0,a,(a+b)/2),
  decode(r,0,(a+b)/2, b) from cte, duo
 where b-a > 1е-6
)
Select * from cte 



Собственно, громоздкая вторая строчка с decode, которую я хочу избежать.
...
Рейтинг: 0 / 0
Фрактальный RCTE
    #40021003
НеофитSQL
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Оказывается, в ms SQL можно писать RCTE с несколькими union all..

Оракл, почему ограничение?
...
Рейтинг: 0 / 0
Фрактальный RCTE
    #40021005
booby
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
вот это?
Код: plsql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
with divider as(
  select 1 as d from dual
  union all
  select 2 from dual
  )
--select d from divider  
, fract(n_left, n_right) as (
  Select 1 as n_left, 2 as n_right From dual
  union all 
  Select 
    case td.d when 1 then tf.n_left else round((tf.n_left + tf.n_right)/2,38) end as n_left
  , case td.d when 1 then round((tf.n_left +tf.n_right)/2,38) else tf.n_right end as n_right
  from fract tf, divider td
)
CYCLE n_left SET cyclemark TO 'X' DEFAULT '-'
select * from fract
where rownum < 21



А "почему ограничение" - лучше на asktom спрашивать...
...
Рейтинг: 0 / 0
Фрактальный RCTE
    #40021032
НеофитSQL
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
booby
вот это?
Код: plsql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
with divider as(
  select 1 as d from dual
  union all
  select 2 from dual
  )
--select d from divider  
, fract(n_left, n_right) as (
  Select 1 as n_left, 2 as n_right From dual
  union all 
  Select 
    case td.d when 1 then tf.n_left else round((tf.n_left + tf.n_right)/2,38) end as n_left
  , case td.d when 1 then round((tf.n_left +tf.n_right)/2,38) else tf.n_right end as n_right
  from fract tf, divider td
)
CYCLE n_left SET cyclemark TO 'X' DEFAULT '-'
select * from fract
where rownum < 21





Да, оно, с ортоджойном.
Сравниваю со своей версией выше, появились вопросы:

decode vs case: я предполагал что в этом случае decode предпочтительнее, т.к. оптимизирован для сравнения констант. Есть ли смысл заменять его на case, или это дело привычки?

round((tf.n_left +tf.n_right)/2,38) необычная конструкция, на первый взгляд ничего не дающая, на второй взгляд ухудшающая точность. Есть ли смысл в этой конструкции, о котором я не знаю?
...
Рейтинг: 0 / 0
Фрактальный RCTE
    #40021049
Фотография SY
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Код: 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.
with divider
  as (
      select 0 as d from dual union all
      select 1 from dual
     ),
fract(n_left,n_right)
 as (
      select  1 n_left,
              2 n_right
        from  dual
     union all 
      select  tf.n_left + td.d * (tf.n_right - tf.n_left) / 2 n_left,
              tf.n_right - (1 - td.d) * (tf.n_right - tf.n_left) / 2 n_right
        from  fract tf,
              divider td
        where tf.n_right - tf.n_left >= 0.2 -- double min interval length
    )
select  n_left,
        n_right
  from  fract
/

    N_LEFT    N_RIGHT
---------- ----------
         1          2
         1        1.5
       1.5          2
         1       1.25
      1.25        1.5
       1.5       1.75
      1.75          2
         1      1.125
     1.125       1.25
      1.25      1.375
     1.375        1.5
       1.5      1.625
     1.625       1.75
      1.75      1.875
     1.875          2

15 rows selected.

SQL>



SY.
...
Рейтинг: 0 / 0
Фрактальный RCTE
    #40021051
НеофитSQL
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
SY, спасибо. Я понял про арифметику, условный оператор decode был для более общего случая, тут действительно можно обойтись без условных операторов.

Из всех ответов я понял, что для Оракла в таких случаях принято размножать вторую и неповторимую строчку RCTE через кросс-джойн с вспомогательной таблицей.
...
Рейтинг: 0 / 0
7 сообщений из 7, страница 1 из 1
Форумы / Oracle [игнор отключен] [закрыт для гостей] / Фрактальный RCTE
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


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