Видимость внешних таблиц в CROSS APPLY
Казалось бы, значение из строки внешнего датасета должен быть видимым внутри. Рабочий пример:
WITH table_1 AS (
SELECT 1 col_id FROM dual UNION ALL
SELECT 2 col_id FROM dual UNION ALL
SELECT 4 col_id FROM dual
),
table_2 AS (
SELECT 1 col_id, 2 val FROM dual UNION ALL
SELECT 2 col_id, 5 val FROM dual UNION ALL
SELECT 6 col_id, 7 val FROM dual
),
table_3 AS (
SELECT 1 col_id, 2 val FROM dual UNION ALL
SELECT 2 col_id, 5 val FROM dual UNION ALL
SELECT 6 col_id, 7 val FROM dual
)
SELECT *
FROM table_1 t1
CROSS APPLY (SELECT *
FROM table_2 t2
WHERE t2.col_id in (SELECT t2.col_id
FROM table_3 t3
WHERE t2.col_id = t1.col_id));
Но почему-то в случае рекурсивного запроса я столкнулся с проблемой видимости. Не рабочий пример:
WITH table_1 AS (
SELECT 1 col_id FROM dual UNION ALL
SELECT 2 col_id FROM dual UNION ALL
SELECT 4 col_id FROM dual
),
table_parents AS (
SELECT 1 col_id, 3 parent_id, 'manager' parent_type FROM dual UNION ALL
SELECT 2 col_id, 3 parent_id, 'manager' parent_type FROM dual UNION ALL
SELECT 3 col_id, 4 parent_id, 'manager' parent_type FROM dual
)
SELECT t1.col_id
, uptimate_parent.parent_id
FROM table_1 t1
CROSS APPLY (SELECT parent_id
FROM (select col_id, parent_id FROM table_parents WHERE parent_type = 'manager') pars
WHERE connect_by_isleaf = 1
START WITH pars.col_id = t1.col_id
CONNECT BY NOCYCLE PRIOR pars.parent_id = pars.col_id) uptimate_parent;
Этот код вызовет ошибку:
[42000][904] ORA-00904: "T1"."COL_ID": invalid identifier
ругаясь на обращение внутри CROSS APPLY. В чем я не правильно понимаю логику CROSS APPLY здесь, почему во втором случае подзапрос не видит значение из строки в месте вызова подзапроса?
Самое интересное, что просто переместив CROSS APPLY подзапрос в SELECT-лист, запрос становится вполне рабочим (да, в тестовых данных не случайно высший родитель только один). То есть этот запрос вполне рабочий:
WITH table_1 AS (
SELECT 1 col_id FROM dual UNION ALL
SELECT 2 col_id FROM dual UNION ALL
SELECT 4 col_id FROM dual
),
table_parents AS (
SELECT 1 col_id, 3 parent_id, 'manager' parent_type FROM dual UNION ALL
SELECT 2 col_id, 3 parent_id, 'manager' parent_type FROM dual UNION ALL
SELECT 3 col_id, 4 parent_id, 'manager' parent_type FROM dual
)
SELECT t1.col_id
, (SELECT parent_id
FROM (select col_id, parent_id FROM table_parents WHERE parent_type = 'manager') pars
WHERE connect_by_isleaf = 1
START WITH pars.col_id = t1.col_id
CONNECT BY NOCYCLE PRIOR pars.parent_id = pars.col_id) uptimate_parent
FROM table_1 t1;