Добро пожаловать в форум, Guest  >>   Войти | Регистрация | Поиск | Правила | В избранное | Подписаться
Все форумы / Oracle Новый топик    Ответить
 Фрактальный RCTE  [new]
НеофитSQL
Member [заблокирован]

Откуда: Маями
Сообщений: 760
Пытаюсь рекурсивно сгенерить фрактал
0-1
0-.5, 0.5-1
0-.25, .25-.5, .5-.75, .75-1
И т.д.

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

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?
20 ноя 20, 23:30    [22236271]     Ответить | Цитировать Сообщить модератору
 Re: Фрактальный RCTE  [new]
НеофитSQL
Member [заблокирован]

Откуда: Маями
Сообщений: 760
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, которую я хочу избежать.
21 ноя 20, 00:48    [22236295]     Ответить | Цитировать Сообщить модератору
 Re: Фрактальный RCTE  [new]
НеофитSQL
Member [заблокирован]

Откуда: Маями
Сообщений: 760
Оказывается, в ms SQL можно писать RCTE с несколькими union all..

Оракл, почему ограничение?
21 ноя 20, 14:52    [22236399]     Ответить | Цитировать Сообщить модератору
 Re: Фрактальный RCTE  [new]
booby
Member

Откуда:
Сообщений: 2255
вот это?
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 спрашивать...
21 ноя 20, 15:08    [22236403]     Ответить | Цитировать Сообщить модератору
 Re: Фрактальный RCTE  [new]
НеофитSQL
Member [заблокирован]

Откуда: Маями
Сообщений: 760
booby
вот это?
+
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) необычная конструкция, на первый взгляд ничего не дающая, на второй взгляд ухудшающая точность. Есть ли смысл в этой конструкции, о котором я не знаю?
21 ноя 20, 20:35    [22236460]     Ответить | Цитировать Сообщить модератору
 Re: Фрактальный RCTE  [new]
SY
Member

Откуда: Middlebury, CT USA
Сообщений: 10051
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.

Сообщение было отредактировано: 22 ноя 20, 01:16
22 ноя 20, 01:07    [22236495]     Ответить | Цитировать Сообщить модератору
 Re: Фрактальный RCTE  [new]
НеофитSQL
Member [заблокирован]

Откуда: Маями
Сообщений: 760
SY, спасибо. Я понял про арифметику, условный оператор decode был для более общего случая, тут действительно можно обойтись без условных операторов.

Из всех ответов я понял, что для Оракла в таких случаях принято размножать вторую и неповторимую строчку RCTE через кросс-джойн с вспомогательной таблицей.
22 ноя 20, 01:34    [22236499]     Ответить | Цитировать Сообщить модератору
Все форумы / Oracle Ответить