Слишком много first_value в запросе? - PullRequest
0 голосов
/ 18 октября 2019

Я хочу получить первый счет по дате каждого po_distribution_id и его данным:

SELECT UNIQUE 
first_value(i.invoice_id) OVER (PARTITION BY po_distribution_id ORDER BY i.invoice_date asc) invoice_id
,first_value(i.invoice_date) OVER (PARTITION BY po_distribution_id ORDER BY i.invoice_date asc) invoice_date
,first_value(i.invoice_num) OVER (PARTITION BY po_distribution_id ORDER BY i.invoice_date asc) invoice_date
FROM AP_INVOICE_DISTRIBUTIONS_ALL d LEFT JOIN ap_invoices_all i on d.invoice_id = i.invoice_id
WHERE sysdate - i.invoice_date < 30
ORDER BY invoice_id DESC

Интересно, есть ли лучший способ выполнить это, не используя так много first_value. Запрос не медленный, но я чувствую себя неловко с ним.

Пример:

po_distribution_id  invoice_id  invoice_date
212121              2212        2019-05-05
212121              2355        2019-01-09
212121              1122        2019-02-02
212121              7744        2019-03-04

Должен вернуть:

po_distribution_id  invoice_id  invoice_date
212121              2355        2019-01-09

Ответы [ 2 ]

1 голос
/ 18 октября 2019

Если для каждого po_distribution_id даты выставления счетов различны (если нет, вопрос, в первую очередь, не имеет большого смысла - вы должны объяснить, как вы разрываете связи), тогда вы неТ аналитические функции вообще не нужны. Агрегатные функции (в частности, функция FIRST()) могут выполнять эту работу и намного быстрее.

select po_distribution_id, 
       min(invoice_id) keep (dense_rank first order by invoice_date) as invoice_id,
       min(invoice_date) as invoice_date
from   [........]
where  [........]
group  by po_distribution_id
order  by [........]
1 голос
/ 18 октября 2019

Все три функции first_value() используют один и тот же раздел, но последний имеет другой порядок (invoice_date, против invoice_num в первых двух). Если порядок invoice_num и invoice_date одинаков, то вы можете использовать row_number() в подзапросе и отфильтровать во внешнем запросе:

select *
from (
    select 
        i.invoice_id,
        i.invoice_date,
        i.invoice_num,
        row_number() over(partition by po_distribution_id order by i.invoice_num) rn
    from 
        ap_invoice_distributions_all d 
        left join ap_invoices_all i on d.invoice_id = i.invoice_id
    where sysdate - i.invoice_date < 30
) x
where rn = 1
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...