Первая попытка
Не могу проверить это, не имея фактическую структуру таблицы и данные, но у меня сделал несколько незначительных изменений, которые иногда оказывают большое влияние.
Прежде всего, я сменил LEFT JOIN
на with
на INNER JOIN
. Поскольку вы используете значения a
в предложении WHERE
, он будет функционировать как inner join
в любом случае, и это, как правило, намного быстрее, особенно с этим количеством данных и соответствующими индексами.
Я изменил внутренний CASE
на NVL
, потому что это по существу то, что он делает. Не знаю, ускорит ли это.
Перемещено конкатенация строк из внешнего запроса на часть with
.
Это лишь небольшие изменения, которые могут иметь место от нуля до совершенно определенного эффекта. По крайней мере, вы можете попробовать их, прежде чем изменять структуру таблицы, хотя в любом случае это может быть хорошей идеей.
WITH t AS
(
SELECT
a.acc_id,
t1.as,
t1.cust,
t1.curr,
t1.code,
t1.depart,
t1.sdate,
t1.stype,
t1.amount,
t1.s_id,
t1.cust || t1.curr || LPAD(t1.code, 4, '0') || LPAD(t1.depart, 3, '0') as groupfield
FROM
table1 t1
INNER JOIN Accs a
ON SUBSTR(a.acc_id, 7, 12) = t1.curr || LPAD(t1.code, 4, '0') || LPAD(t1.depart, 3, '0')
WHERE
t1.sdate = '20.11.2011' AND t1.stype = 'A' AND a.month = 11 ANd a.year = 2011
)
SELECT
MAX(t.s_id),
(CASE WHEN t.as = '000000' THEN
NVL(ac2.acc_id, t.acc_id)
ELSE
t.groupfield
END) acc_id
FROM
t
LEFT JOIN t ac2 on ac2
ON SUBSTR(ac2.acc_id, 1, 6) = '000' || LPAD(t.depart, 3, '0')
GROUP BY
(CASE WHEN t.as = '000000' THEN
NVL(ac2.acc_id, t.acc_id)
ELSE
t.groupfield
END)
Вторая попытка
Посмотрев немного больше в вашем запросе, интересно, если вы не можете просто сделать это один/простой запрос вместо использования with
. Я думаю, что сначала присоединившись к Accs, а затем снова присоединился к Accs с дополнительным условием, вы - хороший способ пойти на самом деле.
SELECT
MAX(t1.s_id) AS s_id,
CASE WHEN t.as = '000000' THEN
NVL(a2.acc_id, a.acc_id)
ELSE
t1.cust || t1.curr || LPAD(t1.code, 4, '0') || LPAD(t1.depart, 3, '0')
END AS acc_id
FROM
table1 t1
INNER JOIN Accs a
ON SUBSTR(a.acc_id, 7, 12) = t1.curr || LPAD(t1.code, 4, '0') || LPAD(t1.depart, 3, '0')
AND a.month = 11 AND a.year = 2011
LEFT JOIN Accs a2
ON SUBSTR(a2.acc_id, 7, 12) = t1.curr || LPAD(t1.code, 4, '0') || LPAD(t1.depart, 3, '0')
AND a2.month = 11 AND a2.year = 2011
AND SUBSTR(a2.acc_id, 1, 6) = '000' || LPAD(t1.depart, 3, '0')
WHERE
t1.sdate = '20.11.2011' AND t1.stype = 'A'
GROUP BY
CASE WHEN t.as = '000000' THEN
NVL(a2.acc_id, a.acc_id)
ELSE
t1.cust || t1.curr || LPAD(t1.code, 4, '0') || LPAD(t1.depart, 3, '0') as groupfield
END AS acc_id
Я сомневаюсь, что вы могли бы ускорить это. многие ваши соединения выполняются по вычисленным результатам, что означает, что индексы не могут использоваться. –
Есть ли другой более быстрый способ сделать то же самое? – DmitryB
Храните эти вычисленные поля в производных полях (что несколько денормирует тики), но позволяет использовать индексы. –