Гость
Форумы / Oracle [игнор отключен] [закрыт для гостей] / Фрактальный RCTE / 7 сообщений из 7, страница 1 из 1
20.11.2020, 23:30
    #40020929
НеофитSQL
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Фрактальный RCTE
Пытаюсь рекурсивно сгенерить фрактал
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
21.11.2020, 00:48
    #40020935
НеофитSQL
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Фрактальный RCTE
Код: 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
21.11.2020, 14:52
    #40021003
НеофитSQL
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Фрактальный RCTE
Оказывается, в ms SQL можно писать RCTE с несколькими union all..

Оракл, почему ограничение?
...
Рейтинг: 0 / 0
21.11.2020, 15:08
    #40021005
booby
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Фрактальный RCTE
вот это?
Код: 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
21.11.2020, 20:35
    #40021032
НеофитSQL
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Фрактальный RCTE
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
22.11.2020, 01:07
    #40021049
SY
SY
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Фрактальный RCTE
Код: 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
22.11.2020, 01:34
    #40021051
НеофитSQL
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Фрактальный RCTE
SY, спасибо. Я понял про арифметику, условный оператор decode был для более общего случая, тут действительно можно обойтись без условных операторов.

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


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