powered by simpleCommunicator - 2.0.53     © 2025 Programmizd 02
Форумы / Oracle [игнор отключен] [закрыт для гостей] / Есть ли у CTE преимущества перед подзапросом?
25 сообщений из 28, страница 1 из 2
Есть ли у CTE преимущества перед подзапросом?
    #39892297
Alibek B
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
У меня есть многоэтажный запрос на пару сотен строк.
В запросе есть такое выражение:
Код: plsql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
with DEPO as 
(
  select ...
  from ...
  where (T.DATE_WORK_END is null or T.DATE_WORK_END > sysdate)
  and RT.NAME like 'Депозит / %'
)
select ...
from ...
left join DEPO DE on (DE.BASE = EQP.BASE and DE.DEVICE = EQP.DEVICE and EQP.GUIDED = 1)
left join DEPO DD on (DD.BASE = EQP.BASE and DD.DEVICE = '*' and EQP.DEVICE is not null)
left join DEPO DZ on (DZ.BASE = 4866     and DZ.DEVICE = '-' and EQP.DEVICE is null)
left join DEPO DE1 on (DE1.BASE = S1.TARIFF_ID and DE1.DEVICE = EQP.DEVICE and EQP.GUIDED = 1)
left join DEPO DD1 on (DD1.BASE = S1.TARIFF_ID and DD1.DEVICE = '*' and EQP.DEVICE is not null)
left join DEPO DZ1 on (DZ1.BASE = S1.TARIFF_ID and DZ1.DEVICE = '-' and EQP.DEVICE is null)
left join DEPO DE2 on (DE2.BASE = S2.TARIFF_ID and DE2.DEVICE = EQP.DEVICE and EQP.GUIDED = 1)
left join DEPO DD2 on (DD2.BASE = S2.TARIFF_ID and DD2.DEVICE = '*' and EQP.DEVICE is not null)
left join DEPO DZ2 on (DZ2.BASE = S2.TARIFF_ID and DZ2.DEVICE = '-' and EQP.DEVICE is null)
...


Я хочу убрать CTE и в этих девяти джойнах использовать подзапросы, что позволит использовать более точные и простые выражения в where/on (а в некоторых случаях еще и избавиться от лишнего join в подзапросе). Но основная причина в том, что это позволит для получения исторических записей использовать не sysdate, а другое значение даты — на данный момент этого не требуется, но в будущем это может быть полезным. Но большие, но по пять вместо одного компактного DEPO к и без того громоздкому запросу добавится еще почти сотня строк.
Есть ли у CTE преимущества в производительности/нагрузке?
...
Рейтинг: 0 / 0
Есть ли у CTE преимущества перед подзапросом?
    #39892303
Фотография -2-
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Alibek B.
Есть ли у CTE преимущества в производительности/нагрузке?
explain plan, 10053.
Если смущает производительность, имеет смысл сравнить вариант без многократного джоина одного и того же.
...
Рейтинг: 0 / 0
Есть ли у CTE преимущества перед подзапросом?
    #39892314
Фотография Stax
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Alibek B.,

какая причина переделок?

ps
можно попробовать многочисленные left join DEPO заменить одним left join DEPO со сложным он/вхере

разультат оформить "unpivot"-ом

.....
stax
...
Рейтинг: 0 / 0
Есть ли у CTE преимущества перед подзапросом?
    #39892334
Alibek B
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Stax
какая причина переделок?

Одна из причин - мне (могут быть) нужны исторические данные на определенный момент, например на S1.CREATE_DATE. В варианте с CTE S1 ещё не определен.
...
Рейтинг: 0 / 0
Есть ли у CTE преимущества перед подзапросом?
    #39892395
Фотография Stax
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Alibek B.,

Два варианта скриптов не рассматриваются (на текущую и архивную)?

зы
иногда архівные данные в других "исторических" таблицах

.....
stax
...
Рейтинг: 0 / 0
Есть ли у CTE преимущества перед подзапросом?
    #39892448
Фотография Sayan Malakshinov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Модератор форума
Alibek B.
Есть ли у CTE преимущества в производительности/нагрузке?
зависит от... Главное отличие в том, что он может быть материализован, т.е. не придется вычитывать одни и те же данные из оригинальной таблицы по многу раз.
...
Рейтинг: 0 / 0
Есть ли у CTE преимущества перед подзапросом?
    #39892471
Alibek B
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Stax
можно попробовать многочисленные left join DEPO заменить одним left join DEPO со сложным он/вхере

У меня это не удалось.
У меня есть записи, у них есть дочерние записи, а у дочерних записей есть свои дочерние записи. И вот по этим дочерним записям второго уровня мне нужно получить определенное значение в соответствии с определенным приоритетом.

xtender
Главное отличие в том, что он может быть материализован, т.е. не придется вычитывать одни и те же данные из оригинальной таблицы по многу раз.

Да, я это помню.
Но у меня результат в CTE само по себе малострочный, запрос CTE возвращает буквально пару-тройку десятков записей. Да и в оригинальных таблицах записей немного (сотни или несколько сотен строк).
Будет ли эффект от материализации такого небольшого фрагмента данных?
...
Рейтинг: 0 / 0
Есть ли у CTE преимущества перед подзапросом?
    #39892482
Фотография SY
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Alibek B.

Но у меня результат в CTE само по себе малострочный, запрос CTE возвращает буквально пару-тройку десятков записей.


Не столь важно сколько строк возвращает CTE а сколько времени это занимает. Кроме того материализация часто избавляет от необходимости предотвращения unnesting/expanding,...

SY.
...
Рейтинг: 0 / 0
Есть ли у CTE преимущества перед подзапросом?
    #39892689
Alibek B
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
SY
Не столь важно сколько строк возвращает CTE а сколько времени это занимает.

Я и имел ввиду, что запрос внутри CTE простой, выполняется миллисекунды.
Но основные моменты я понял.
К сожалению, похоже что придется переносить из CTE в подзапросы, мне все же нужно получать исторические данные не на sysdate, а на момент из выборки данных.
...
Рейтинг: 0 / 0
Есть ли у CTE преимущества перед подзапросом?
    #39892713
Фотография Stax
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Alibek B.

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


-2-

... имеет смысл сравнить вариант без многократного джоина одного и того же.


.....
stax
...
Рейтинг: 0 / 0
Есть ли у CTE преимущества перед подзапросом?
    #39893319
Alibek B
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Конечный вариант запроса:
Код: plsql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
with DEPO as
(
  select ...
  from ...
  where RT.NAME like 'Депозит / %'
)
select ...
from ...
left join DEPO DE on (DE.BASE = EQP.BASE and DE.DEVICE = EQP.DEVICE and EQP.GUIDED = 1          and (DE.T_BEG  <= AA.MOMENT and (DE.T_END  is null or DE.T_END  > AA.MOMENT)) and (DE.TE_BEG  <= AA.MOMENT and (DE.TE_END  is null or DE.TE_END  > AA.MOMENT)))
left join DEPO DD on (DD.BASE = EQP.BASE and DD.DEVICE = '*' and EQP.DEVICE is not null         and (DD.T_BEG  <= AA.MOMENT and (DD.T_END  is null or DD.T_END  > AA.MOMENT)) and (DD.TE_BEG  <= AA.MOMENT and (DD.TE_END  is null or DD.TE_END  > AA.MOMENT)))
left join DEPO DZ on (DZ.BASE = 4866     and DZ.DEVICE = '-' and EQP.DEVICE is null             and (DZ.T_BEG  <= AA.MOMENT and (DZ.T_END  is null or DZ.T_END  > AA.MOMENT)) and (DZ.TE_BEG  <= AA.MOMENT and (DZ.TE_END  is null or DZ.TE_END  > AA.MOMENT)))
left join DEPO DE1 on (DE1.BASE = S1.TARIFF_ID and DE1.DEVICE = EQP.DEVICE and EQP.GUIDED = 1   and (DE1.T_BEG <= AA.MOMENT and (DE1.T_END is null or DE1.T_END > AA.MOMENT)) and (DE1.TE_BEG <= AA.MOMENT and (DE1.TE_END is null or DE1.TE_END > AA.MOMENT)))
left join DEPO DD1 on (DD1.BASE = S1.TARIFF_ID and DD1.DEVICE = '*' and EQP.DEVICE is not null  and (DD1.T_BEG <= AA.MOMENT and (DD1.T_END is null or DD1.T_END > AA.MOMENT)) and (DD1.TE_BEG <= AA.MOMENT and (DD1.TE_END is null or DD1.TE_END > AA.MOMENT)))
left join DEPO DZ1 on (DZ1.BASE = S1.TARIFF_ID and DZ1.DEVICE = '-' and EQP.DEVICE is null      and (DZ1.T_BEG <= AA.MOMENT and (DZ1.T_END is null or DZ1.T_END > AA.MOMENT)) and (DZ1.TE_BEG <= AA.MOMENT and (DZ1.TE_END is null or DZ1.TE_END > AA.MOMENT)))
left join DEPO DE2 on (DE2.BASE = S2.TARIFF_ID and DE2.DEVICE = EQP.DEVICE and EQP.GUIDED = 1   and (DE2.T_BEG <= AA.MOMENT and (DE2.T_END is null or DE2.T_END > AA.MOMENT)) and (DE2.TE_BEG <= AA.MOMENT and (DE2.TE_END is null or DE2.TE_END > AA.MOMENT)))
left join DEPO DD2 on (DD2.BASE = S2.TARIFF_ID and DD2.DEVICE = '*' and EQP.DEVICE is not null  and (DD2.T_BEG <= AA.MOMENT and (DD2.T_END is null or DD2.T_END > AA.MOMENT)) and (DD2.TE_BEG <= AA.MOMENT and (DD2.TE_END is null or DD2.TE_END > AA.MOMENT)))
left join DEPO DZ2 on (DZ2.BASE = S2.TARIFF_ID and DZ2.DEVICE = '-' and EQP.DEVICE is null      and (DZ2.T_BEG <= AA.MOMENT and (DZ2.T_END is null or DZ2.T_END > AA.MOMENT)) and (DZ2.TE_BEG <= AA.MOMENT and (DZ2.TE_END is null or DZ2.TE_END > AA.MOMENT)))
...


То есть в CTE я получаю все версии данных, а нужную версию (на нужный момент) получаю при JOIN.
Уж слишком громоздким получается запрос, если делать подзапросы.

Но есть еще один небольшой вопрос.
Для получения нужной версии данных я использую момент AA.MOMENT.
Но это компромиссное значение, более правильным было бы использовать такое значение:
Код: plsql
1.
2.
3.
4.
5.
6.
7.
8.
case
  when EQP.SERVICE_ID is not null then EQP.STARTED
  when S1.SERVICE_ID is null and S2.SERVICE_ID is null then C.CREATE_DATE
  when S1.SERVICE_ID is not null and S2.SERVICE_ID is not null then greatest(S1.STARTED, S2.STARTED)
  when S1.SERVICE_ID is not null then S1.STARTED
  when S2.SERVICE_ID is not null then S2.STARTED
  else AA.MOMENT
end as MOMENT


Добавлять такое значение в критерии ON я не рискнул, серверу это может быть и безразлично, но я сам в таком запросе запутаюсь.

Я хотел схитрить и сделать так:
Код: plsql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
...
from ...
join (
select case
  when EQP.SERVICE_ID is not null then EQP.STARTED
  when S1.SERVICE_ID is null and S2.SERVICE_ID is null then C.CREATE_DATE
  when S1.SERVICE_ID is not null and S2.SERVICE_ID is not null then greatest(S1.STARTED, S2.STARTED)
  when S1.SERVICE_ID is not null then S1.STARTED
  when S2.SERVICE_ID is not null then S2.STARTED
  else AA.MOMENT
end as MOMENT
from DUAL
) V on (1=1)
left join DEPO DE on (DE.BASE = EQP.BASE and DE.DEVICE = EQP.DEVICE and EQP.GUIDED = 1          and (DE.T_BEG  <= V.MOMENT and (DE.T_END  is null or DE.T_END  > V.MOMENT)) and (DE.TE_BEG  <= AA.MOMENT and (DE.TE_END  is null or DE.TE_END  > V.MOMENT)))
...


но разумеется это не сработало, внутри подзапроса нет доступа к внешнему контексту (во всяком случае при использовании подзапроса внутри FROM).

Не подскажите, есть ли способ для подобного случая, чтобы сложное выражение можно было представить как виртуальный столбец?
Ну кроме как оформления всего предшествующего текста запроса в CTE или подзапрос, и присоединения DEPO к этому CTE/подзапросу?
...
Рейтинг: 0 / 0
Есть ли у CTE преимущества перед подзапросом?
    #39893767
Фотография Stax
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Alibek B.

Не подскажите, есть ли способ для подобного случая, чтобы сложное выражение можно было представить как виртуальный столбец?

гляньте, темка недавно была
что-то типа латерал и "сложное выражение"

зи
по старинке s1,s2 в подзапрос аа и вычислить AA.MOMENT

.....
stax
...
Рейтинг: 0 / 0
Есть ли у CTE преимущества перед подзапросом?
    #39893902
andreymx
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
если в CTE написать NVL(T_END, date '3999-12-31') T_END и NVL(TE_END, date '3999-12-31') TE_END
то весь код станет немного короче и прозрачнее
Код: plsql
1.
2.
3.
4.
вместо
(DZ2.T_BEG <= AA.MOMENT and (DZ2.T_END is null or DZ2.T_END > AA.MOMENT))
будет
AA.MOMENT between DZ2.T_BEG and DZ2.T_END
...
Рейтинг: 0 / 0
Есть ли у CTE преимущества перед подзапросом?
    #39893922
Alibek B
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Использование функций разве не приведет к тому, что индекс не будет использоваться?
К тому же between это закрытый диапазон, а у меня верхняя граница открытая.
...
Рейтинг: 0 / 0
Есть ли у CTE преимущества перед подзапросом?
    #39894059
Фотография andrey_anonymous
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Alibek B.
Использование функций разве не приведет к тому, что индекс не будет использоваться?
К тому же between это закрытый диапазон, а у меня верхняя граница открытая.

А between - что, функция? Дайте пожалуйста ссылку почитать.
Закрытый диапазон для типа date решается выражением DZ2.T_END-1/86400
...
Рейтинг: 0 / 0
Есть ли у CTE преимущества перед подзапросом?
    #39894092
Alibek B
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
andrey_anonymous
А between - что, функция?

Функция это NVL. Если я индексированный столбец указываю внутри функции (да еще и недетерминированной), то индекс при сравнении результата использоваться не будет. А как сравнивать, с помощью < или between, уже значения не имеет.

andrey_anonymous
Закрытый диапазон для типа date решается выражением DZ2.T_END-1/86400

Это же некрасиво.
А если время фиксируется с точностью до долей секунды?
...
Рейтинг: 0 / 0
Есть ли у CTE преимущества перед подзапросом?
    #39894095
Alibek B
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Stax
гляньте, темка недавно была
что-то типа латерал и "сложное выражение"

Почитал, любопытная возможность, я про нее и не слышал раньше.
Но доступно с Oracle 12c, а у меня Oracle 10g.
В моей версии доступно, похоже, только обрамление в подзапрос.
...
Рейтинг: 0 / 0
Есть ли у CTE преимущества перед подзапросом?
    #39894102
Фотография andrey_anonymous
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Alibek B.
andrey_anonymous
А between - что, функция?

Функция это NVL. Если я индексированный столбец указываю внутри функции (да еще и недетерминированной), то индекс при сравнении результата использоваться не будет.

А у Вас оба атрибута проиндексированы, и дата начала, и дата завершения?
- продемонстрируйте, как предполагаете использовать оба индекса для доступа к данным.
- как предполагаете использовать индекс на t_end, если t_end допускает null?

Alibek B.

andrey_anonymous
Закрытый диапазон для типа date решается выражением DZ2.T_END-1/86400

Это же некрасиво.
А если время фиксируется с точностью до долей секунды?

Если время фиксируется с точностью до долей секунды, то это уже не date :)
Что касается красоты - вопрос дискуссионный.
1/86400, 1/1440 лично для меня уже много лет как хорошо узнаваемые и осмысленные паттерны.
А вот разносить логически связанные условия даты на два отдельных выражения мне не очень нравится - это плохо читается в сложных запросах.
Ну и последнее: если строите версионные объекты, то лучше проектировать их под between - т.е. не допускать null и пересечений на границах версий.
...
Рейтинг: 0 / 0
Есть ли у CTE преимущества перед подзапросом?
    #39894103
Фотография Stax
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Alibek B.

Но доступно с Oracle 12c, а у меня Oracle 10g.

попробовал через table(кажись была в десятке)
но почему-то не видит d
Код: plsql
1.
2.
3.
4.
5.
6.
7.
  1  select * from dept d ,table(select sys.odcinumberlist( sin(d.deptno)) s from dual ) l
  2*  left join emp e on (e.deptno=d.deptno and sal>value(l))
SQL> /
 left join emp e on (e.deptno=d.deptno and sal>value(l))
                              *
ERROR at line 2:
ORA-00904: "D"."DEPTNO": invalid identifier



с латерал пашет
Код: plsql
1.
2.
select * from dept d ,lateral(select sin(d.deptno) s from dual ) l
 left join emp e on (e.deptno=d.deptno and sal>l.s)



.....
stax
...
Рейтинг: 0 / 0
Есть ли у CTE преимущества перед подзапросом?
    #39894106
Фотография andrey_anonymous
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Stax
Alibek B.

у меня Oracle 10g.

Код: plsql
1.
  2*  left join emp e on (e.deptno=d.deptno and sal>value(l))

...
Рейтинг: 0 / 0
Есть ли у CTE преимущества перед подзапросом?
    #39894113
Фотография Stax
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
andrey_anonymous,

я пробую на 11-ке

у Alibek B. наверняка ж есть left join

так d видит
Код: plsql
1.
2.
3.
4.
5.
6.
7.
8.
9.
select * from dept d ,table(select sys.odcinumberlist( sin(d.deptno)) s from dual ) l,emp e 
where e.deptno=d.deptno and sal>value(l)
/
SQL> /

    DEPTNO DNAME          LOC           COLUMN_VALUE      EMPNO ENAME      JOB              MGR HIREDATE        SAL       COMM     DEPTNO
---------- -------------- ------------- ------------ ---------- ---------- --------- ---------- -------- ---------- ---------- ----------
        10 ACCOUNTING     NEW YORK        -,54402111       7934 MILLER     CLERK           7782 23.01.82       1300                    10
...



.....
stax
...
Рейтинг: 0 / 0
Есть ли у CTE преимущества перед подзапросом?
    #39894116
Alibek B
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
andrey_anonymous

Ну и последнее: если строите версионные объекты, то лучше проектировать их под between - т.е. не допускать null и пересечений на границах версий.

Полуоткрытые диапазоны мне кажутся намного более правильными и удобными, чем закрытые. Они не зависят от дискретности используемых значений.
Если бы я проектировал таблицы, я бы оставил такой же принцип задания периода, просто сделал поле END обязательным (не допускающим null) и с дефолтным значением 9999-01-01.
...
Рейтинг: 0 / 0
Есть ли у CTE преимущества перед подзапросом?
    #39894122
Фотография andrey_anonymous
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Alibek B.
andrey_anonymous

Ну и последнее: если строите версионные объекты, то лучше проектировать их под between - т.е. не допускать null и пересечений на границах версий.

Полуоткрытые диапазоны мне кажутся
...
с дефолтным значением 9999-01-01.

Кажутся. Но не беда, со временем понимание придет.
Ну и дефолт именно такой я бы не рекомендовал.
Попробуйте создать range-partitioned интервальную таблицу с интервалом 1 день - поймете.
...
Рейтинг: 0 / 0
Есть ли у CTE преимущества перед подзапросом?
    #39894136
Alibek B
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
andrey_anonymous
Кажутся. Но не беда, со временем понимание придет.

А какие будут аргументы?
У меня (помимо "это красиво") в пользу полуоткрытых диапазонов идет то, что из них можно построить непрерывную цепочку версий, когда DATE_BEG следующей записи будет равно DATE_END предыдущей.
А если диапазон будет закрытым, то как понять, между двумя соседними записями есть разрыв в одну секунду или это непрерывная запись?

andrey_anonymous
Попробуйте создать range-partitioned интервальную таблицу с интервалом 1 день - поймете.

Это для больших таблиц и там в любом случае есть свои особенности, которые нужно учитывать в ущерб другим особенностям.
А разве для partition-таблиц нет специальных значений "все что больше значения X складывать в секцию OTHER"?
...
Рейтинг: 0 / 0
Есть ли у CTE преимущества перед подзапросом?
    #39894155
Фотография -2-
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Alibek B.
А разве для partition-таблиц нет специальных значений "все что больше значения X складывать в секцию OTHER"?
Вероятно имелось ввиду не столько на "range-partitioned", сколько термин "интервальную".
С другой стороны, партиционирование range как раз пользует открытость справа less than.

Alibek B.
как понять, между двумя соседними записями есть разрыв в одну секунду или это непрерывная запись?
Что открытый, что закрытый - прочитать коммент к полю. С открытым нужно комментировать с какого боку(ов) он открытый, с закрытым дискретность значений.
По поводу "дискретности" стоит припомнить wm_period - он базируется на timestamp, но как раз с ненулевым временем плохоприменим. А ошибка в документации значения max_time повторяется из версии к версии и служит демонстрацией, как легко ошибиться в недозначенияхTable 3-1 Constants for Valid Time SupportThe maximum (latest) timestamp value supported by Workspace Manager. Currently the end of the day (11:59.999999000 pm) on 31-Dec-9999
...
Рейтинг: 0 / 0
25 сообщений из 28, страница 1 из 2
Форумы / Oracle [игнор отключен] [закрыт для гостей] / Есть ли у CTE преимущества перед подзапросом?
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


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