Oracle SQL - создание "несохраненной" процедуры - PullRequest
0 голосов
/ 14 февраля 2020

У меня есть этот SQL запрос

SELECT ACCBAL_DATE, ACCBAL_AMOUNT
FROM ACCOUNT_BALANCES t
WHERE ACC_KEY = '964570223'
AND ACCBAL_KEY = '16'
ORDER BY ACCBAL_DATE DESC
FETCH FIRST 1 ROWS ONLY; 

Он возвращает одну строку, но мне нужно использовать этот запрос для многих ACC_KEYS (около 600).

Итак, первый способ сделать это должен выполнить этот запрос около 600x с другим параметром ACC_KEY.

Второй, я думаю, создает процедуру.

Процедура, которая будет использовать переменную acc_key и переместит ее в оператор WHERE. Проблема в том, что я не могу создать процедуру, хранимую на сервере из-за разрешений.

Есть ли способ решить ее без сохранения процедуры на сервере?

РЕДАКТИРОВАТЬ: я знаю предложение IN, но это это не то, что мне нужно. Мне нужно что-то, что будет выполнять запрос около 600x, каждое выполнение с другим ACC_KEY в предложении WHERE, и результат должен быть 600 строк.

Ответы [ 3 ]

1 голос
/ 14 февраля 2020

когда я использовал их в предложении IN, он все равно будет возвращать только одну строку. Я хочу вернуть только одну строку, потому что без ограничений она возвращает около 100 строк, поэтому мне нужна только первая строка, в которой были нужны данные. Для каждого ACC_KEY он должен возвращать только одну строку

Вы можете сделать это с помощью предложения IN(), в котором перечислены все 600 ключевых значений:

select acc_key,
  max(accbal_date) as accbal_date,
  max(accbal_amount) keep (dense_rank last order by accbal_date) as accbal_amount
from account_balances t
where acc_key in ('964570223', '964570224', ...) -- up to 1000 allowed
and accbal_key = '16'
group by acc_key
order by acc_key;

Это использует агрегатные функции и группировка по ключу, поэтому вы получите по одной строке на ключ с данными за самую последнюю дату.

Подробнее о keep / last .

Это будет все же лучше использовать коллекцию или таблицу - возможно, внешнюю таблицу, загруженную из листа Excel, сохраненную в формате CSV; не в последнюю очередь потому, что вы можете указать только 1000 записей в одном предложении IN() - или в любом списке выражений - но также по соображениям производительности и удобочитаемости / обслуживания.

1 голос
/ 14 февраля 2020

Вы можете сохранить ключи в таблице или использовать производную таблицу в запросе. Я бы порекомендовал что-то более похожее на это:

WITH keys as (
      SELECT '964570223' as ACC_KEY FROM DUAL UNION ALL
      . . . 
     )
SELECT k.ACC_KEY, MAX(ab.ACCBAL_DATE) as ACCBAL_DATE,
       MAX(ab.ACCBAL_AMOUNT) KEEP (DENSE_RANK FIRST ORDER BY ab.ACCBAL_DATE DESC) as ACCBAL_AMOUNT
FROM keys k LEFT JOIN
     ACCOUNT_BALANCES ab
     ON ab.ACC_KEY = k.ACC_KEY AND
        ab.ACCBAL_KEY = '16'
GROUP BY k.ACC_KEY;

Конечно, CTE keys можно заменить таблицей с учетными записями.

Обратите внимание, что это заменяет вашу логику c с логиками агрегации c. Вам просто нужна самая последняя дата и баланс, который Oracle поддерживает с помощью ключевого слова KEEP.

0 голосов
/ 14 февраля 2020

Шаг-1: СОЗДАТЬ ТАБЛИЦУ С 1 КОЛОНКОЙ ACC_KEY СОХРАНЯЕТ ВЕСЬ СПИСОК ACC_KEY.

Шаг-2: Выполнение кода.

SELECT T.ACCBAL_DATE, T.ACCBAL_AMOUNT
FROM ACCOUNT_BALANCES t
WHERE EXISTS(SELECT A.ACC_KEY FROM <TABLENAME> A WHERE A.ACC_KEY=T.ACC_KEY)
AND T.ACCBAL_KEY = '16'
ORDER BY T.ACCBAL_DATE DESC
FETCH FIRST 1 ROWS ONLY;
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...