2016-12-05 2 views
0

У меня есть таблица, в которой хранятся затраты на продукты. Я бы хотел получить среднюю стоимость И последний счет-фактуру для каждого продукта.Подзапрос Oracle в списке

Мое решение было создание суб-выбора, чтобы получить последнюю покупки счета-фактуры, но, к сожалению, я получаю

ORA-00904: "B"."CODPROD": invalid identifier 

Мой запрос

SELECT (b.cod_aux) product, 
    -- here goes code to get average cost, 
    (SELECT round(valorultent, 2) 
    FROM (SELECT valorultent 
      FROM pchistest 
      WHERE codprod = b.codprod 
      ORDER BY dtultent DESC) 
    WHERE ROWNUM = 1) 
FROM pchistest a, pcembalagem b 
WHERE a.codprod = b.codprod 
GROUP BY a.codprod, b.cod_aux 
ORDER BY b.cod_aux 

Короче, что я делаю на суб- select заказывает по наследству и получает первую строку с данным продуктом b.codprod

+1

Редактировать свой вопрос и предоставить образцы данных и желаемые результаты. Неясно, что вы хотите сделать. Например, какие столбцы представляют «цену», что означает «последний счет-фактура покупки»? И какой столбец идентифицирует продукт? –

+3

В версии до версии 12c коррелированный подзапрос может ссылаться на столбец родительского запроса только на один уровень вверх. 'codprod = b.codprod' пересекает два уровня, поэтому ошибка. –

+0

ROWNUM не работает таким образом во вспомогательном запросе. Это относится ко всему запросу. Вам нужно использовать ROW_NUMBER() OVER (PARTITION BY c.valorultent ORDER BY c.dtultent DESC) AS row_no и WHERE row_no = 1 во внешнем запросе. – Doug

ответ

1

Ваша проблема заключается в том, что вы не можете использовать свои псевдонимы столбцов глубже одного подзапроса. Согласно комментариям, это было изменено в 12C, но у меня не было возможности попробовать его, так как хранилище данных, которое я использую, все еще на 11g.

Я хотел бы использовать что-то вроде этого:

SELECT b.cod_aux AS product 
     ,ROUND (r.valorultent, 2) AS valorultent 
FROM pchistest a 
JOIN pcembalagem b ON (a.codprod = b.codprod) 
JOIN (SELECT valorultent 
      ,codprod 
      ,ROW_NUMBER() OVER (PARTITION BY codprod 
            ORDER BY dtultent DESC) 
      AS row_no 
     FROM pchistest) r ON (r.row_no = 1 AND r.codprod = b.codprod) 
GROUP BY a.codprod, b.cod_aux 
ORDER BY b.cod_aux 

избежать подзапросов в ЗЕЬЕСТЕ. В большинстве случаев оптимизатор хочет запустить SELECT для каждого элемента в курсоре, или он делает некоторые сумасшедшие вложенные циклы. Если вы сделаете это как подзапрос в JOIN, Oracle, как правило, обработает строки, которые вы присоединяете; как правило, он более эффективен. Наконец, завершите свои функции для каждого элемента (в данном случае ROUND) в конечном продукте. Это не позволит Oracle делать это на ВСЕ строках, а не только на тех, которые вы используете. Он должен делать это правильно, но он может запутаться в сложных запросах.

ROW_NUMBER() OVER (PARTITION BY ..) - это место, где происходит волшебство. Это добавляет номер строки в каждую группу CODPROD. Это позволяет вырезать верхнюю строку из каждого CODPROD, поэтому это позволяет вам получить самый новый/самый старый/самый большой/наименьший/и т. Д. Из вашего подзапроса. Это также отлично подходит для фильтрации дубликатов.

Смежные вопросы