В чем разница между предложением WITH
и подзапросом?
1. WITH table_name as ( ... )
2. select *
from ( select curr from tableone t1
left join tabletwo t2
on (t1.empid = t2.empid)
) as temp_table
В чем разница между предложением WITH
и подзапросом?
1. WITH table_name as ( ... )
2. select *
from ( select curr from tableone t1
left join tabletwo t2
on (t1.empid = t2.empid)
) as temp_table
Предложение WITH
предназначено для факторинга подзапроса, также известного как общие табличные выражения или CTE:
Предложение WITH query_name позволяет назначить имя блоку подзапроса. Затем вы можете связать блок подзапроса с несколькими местами в запросе, указав имя запроса. Oracle Database оптимизирует запрос, обрабатывая имя запроса как встроенное представление, так и временную таблицу.
В вашем втором примере то, что вы назвали temp_table
, представляет собой встроенное представление, а не временную таблицу.
Во многих случаях выбор для использования сводится к вашему предпочитаемому стилю, и CTE могут сделать код более читаемым, особенно с несколькими уровнями подзапросов (мнения, разумеется, меняются). Если вы ссылаетесь только на просмотр CTE/inline, как только вы, вероятно, не увидите никакой разницы в производительности, и оптимизатор может оказаться в том же плане.
Они особенно полезны, когда вам нужно использовать один и тот же подзапрос в нескольких местах, например, в союзе. Вы можете вывести встроенный просмотр в CTE, чтобы код не повторялся, и он позволяет оптимизатору материализовать его, если он считает, что это было бы полезно.
Например, этот надуманный пример:
select curr from (
select curr from tableone t1
left join tabletwo t2 on (t1.empid = t2.empid)
) temp_table
where curr >= 0
union all
select -1 * curr from (
select curr from tableone t1
left join tabletwo t2 on (t1.empid = t2.empid)
) temp_table
where curr < 0
может быть реорганизовано в:
with temp_table as (
select curr from tableone t1
left join tabletwo t2 on (t1.empid = t2.empid)
)
select curr from temp_table
where curr >= 0
union all
select -1 * curr from temp_table
where curr < 0
Подзапрос больше не должен повторяться. Чем сложнее повторяющийся код, тем более выгодным является использование точки CTE для обслуживания. И чем дороже подзапрос, тем большую выгоду вы можете получить от использования CTE, хотя оптимизатор обычно очень хорошо разбирается в том, что вы делаете в любом случае.
Возможно, нет. Oracle может выполнять множество алгебраических преобразований до фактической оптимизации запроса. Скорее всего, оба запроса будут оцениваться одинаково (у них будет один и тот же план выполнения).
Кроме того, если подзапрос содержит аналитические функции (LEAD/LAG/и т.д.) И если вы хотите отфильтровать результат аналитической функции - с SUBQUERY
подхода SUBQUERY
, вам нужно будет вставить результаты в временную таблицу и выполнить фильтрацию и т.д. для временной таблицы, тогда как с помощью предложения WITH
вы можете использовать результат для фильтрации/группировки /etc в том же запросе
;WITH temp AS
(
SELECT
ID
, StatusID
, DateChanged
, LEAD(StatusID,1) OVER (PARTITION BY ID ORDER BY ID, DateChanged, StatusID) NextStatusID
FROM
myTable
WHERE
ID in (57,58)
)
SELECT
ID
, StatusID
, DateChanged
FROM
temp
WHERE
temp.NextStatusID IS NULL