Не ожидал, что так быстро откликнетесь, спасибо всем, приятно удивлен!
Мне понравились решения _Alex_SMIRNOV_, andrey_anonymous, и хреновый в. (планы выполнения показывают в полтора раза меньшую стоимость, чем в моем варианте и, самое главное, жирный запрос t1 выполняется однократно). Наверное, попробую копать в сторону DENSE_RANK.
andrey_anonymous, осознаю, мне еще надо поучиться задавать вопросы правильно...
как и большинству новичков, задачу мне не удалось описать полностью с первых попыток, забыл/опустил существенные детали. (Например, забыл в постановке сказать, что данные в t1 не уникальны, это несколько усложняет задачку.)
Вообще, заморочек в этом зоопарке хватает..
Итак, в расширяющихся рамках задачи, в порядке поступивших замечаний:
1) ограничения целостности:
t1: все столбцы not null, есть еще столбец x
t2: все столбцы not null, тоже есть x not null (по нему идет partition, об этом далее)
t3: pk(b), тоже есть x not null.
2) существующие индексы:
t1: в табличке t0, на которой построен запрос, есть unique not partitioned index on a (в результате запроса t1.a уже не уникально)
t2: nonunique partitioned index on (a, b)
t3: unique not partitioned index on b,
nonunique partitioned index on c,
nonunique partitioned index on d.
3) схема секционирования:
все таблички (t0,t2,t3) - секционированы по значениям х. Этот х присутствует и в результате запроса t1.
4) данные во всех табличках по секциям распределены равномерно, запрос t1 выполняется либо по всем секциям, либо по одной выбранной секции.
5) данные во все таблички добавляются постоянно в режиме 24Х7, изменяться могут только в t3, все, что добавилось/изменилось надо видеть, т.е. matview, наверное, проблематично.
6) конкуренция - OLTP 24х7, большинство пользователей - писатели (залез, пару строк добавил, ушел).
7) pl код вполне возможен, просто с базовых курсов отложилось чье-то утверждение "все, что можно решить на sql, надо решать на sql, остальное - на pl/sql" и чаще всего именно sql решения в моей практике работали быстрее. Но вот в данной ситуации мое SQL решение мне очень не понравилось и хотел переходить к pl/sql. Этот топик, так сказать, попытка дать шанс решению на SQL :-).
8) и т.д и т.п.:
Чтобы не слишком заморачиваться, для упрощения можно считать, что запрос t1 выполнен по одному значению х. Тогда новые исходные данные:
t1
x | a | aa | 1 | 1 | one | 1 | 2 | two | 1 | 2 | another_two | 1 | 3 | three | 1 | 4 | four | 1 | 4 | four | 1 | 5 | five | 1 | 5 | another_five | 1 | 6 | six | 1 | 7 | seven |
|
t2
x | a | b | 1 | 9 | 3 | 1 | 2 | 1 | 1 | 2 | 2 | 1 | 2 | 3 | 1 | 3 | 4 | 1 | 3 | 5 | 1 | 4 | 3 | 1 | 4 | 5 | 1 | 7 | 2 | 1 | 7 | 4 | 1 | 7 | 5 | 3 | 8 | 7 |
|
t3
x b c d e | 1 1 6 10 first | 1 2 8 5 second | 1 3 8 3 third | 1 4 2 4 fourth | 1 5 2 6 fifth | 1 6 8 5 sixth | 3 7 3 8 seventh |
|
искомый результат
x | a | b | c | d | e | aa | 1 | 1 | | | | | one | 1 | 2 | 2 | 8 | 5 | second | two | 1 | 2 | 2 | 8 | 5 | second | another_two | 1 | 3 | 5 | 2 | 6 | fifth | three | 1 | 4 | 3 | 8 | 3 | third | four | 1 | 4 | 3 | 8 | 3 | third | four | 1 | 5 | | | | | five | 1 | 5 | | | | | another_five | 1 | 6 | | | | | six | 1 | 7 | 2 | 8 | 5 | second | seven |
|
скрипт этих исходных данных
WITH t1 AS
(SELECT 1 x, 1 a, 'one' aa FROM DUAL
UNION ALL SELECT 1, 2, 'two' FROM DUAL
UNION ALL SELECT 1, 2, 'another_two' FROM DUAL
UNION ALL SELECT 1, 3, 'three' FROM DUAL
UNION ALL SELECT 1, 4, 'four' FROM DUAL
UNION ALL SELECT 1, 4, 'four' FROM DUAL
UNION ALL SELECT 1, 5, 'five' FROM DUAL
UNION ALL SELECT 1, 5, 'another_five' FROM DUAL
UNION ALL SELECT 1, 6, 'six' FROM DUAL
UNION ALL SELECT 1, 7, 'seven' FROM DUAL),
t2 AS
(SELECT 1 x, 9 a, 3 b FROM DUAL
UNION ALL SELECT 1, 2, 1 FROM DUAL
UNION ALL SELECT 1, 2, 2 FROM DUAL
UNION ALL SELECT 1, 2, 3 FROM DUAL
UNION ALL SELECT 1, 3, 4 FROM DUAL
UNION ALL SELECT 1, 3, 5 FROM DUAL
UNION ALL SELECT 1, 4, 3 FROM DUAL
UNION ALL SELECT 1, 4, 5 FROM DUAL
UNION ALL SELECT 1, 7, 2 FROM DUAL
UNION ALL SELECT 1, 7, 4 FROM DUAL
UNION ALL SELECT 1, 7, 5 FROM DUAL
UNION ALL SELECT 3, 8, 7 FROM DUAL),
t3 AS
(
SELECT 1 x, 1 b, 6 c, 10 d, 'first' e FROM DUAL
UNION ALL SELECT 1, 2, 8, 5, 'second' FROM DUAL
UNION ALL SELECT 1, 3, 8, 3, 'third' FROM DUAL
UNION ALL SELECT 1, 4, 2, 4, 'fourth' FROM DUAL
UNION ALL SELECT 1, 5, 2, 6, 'fifth' FROM DUAL
UNION ALL SELECT 1, 6, 8, 5, 'sixth' FROM DUAL
UNION ALL SELECT 3, 7, 3, 8, 'seventh' FROM DUAL)