6 votes

Sous-sélection dans oracle

J'essaie de sélectionner le prix le plus récent d'une autre table dans une sous-sélection. Mais je n'arrive pas à trouver comment le faire fonctionner.

C'est ce que j'ai essayé :

select something, somthingelse, 
  (
    select * from 
    (
      select QUOTE_PRICE as old_price
      from price_history
      where price_history.part_no= article_table.part_no
      order by valid_from desc
    ) where rownum=1
  )
from  article_table where rownum < 5

La sous-sélection fonctionne d'elle-même, mais elle ne trouve pas les données suivantes article_table.part_no :

Erreur SQL : ORA-00904 : "article_table ". "part_no" : identifiant invalide

Mise à jour :

Solution actuelle :

select something, somethingelse, (
  SELECT MIN(QUOTE_PRICE) KEEP (DENSE_RANK FIRST ORDER BY valid_from)
  FROM price_history
  WHERE part_no=article_table.part_no
) as old_price
from  article_table a where rownum < 5

6voto

Vincent Malgrat Points 42899

Dans Oracle, les sous-requêtes ne peuvent voir les valeurs des requêtes parentes qu'à un niveau de profondeur. Comme vous avez deux sélections imbriquées, la sélection intérieure ne peut pas voir les valeurs de la sélection extérieure.

Vous pourriez effectuer la jointure en premier :

SELECT something, somthingelse, old_price
  FROM (SELECT a.something, a.somthingelse, p.quote_price old_price,
               row_number() over (PARTITION BY a.part_no 
                                  ORDER BY valid_from DESC) rnk
           FROM article_table a
           LEFT JOIN price_history p ON a.part_no = p.part_no)
 WHERE rnk = 1;

Vous pourriez aussi utiliser une fonction PL/SQL qui renverrait le premier quote_price de price_history lorsqu'on lui donne un article_table.part_no .

2voto

Lukas Eder Points 48046

Essayez le crénelage article_table dans la requête la plus externe :

select a.something, a.somthingelse, 
  (
    select * from 
    (
      select QUOTE_PRICE as old_price
      from price_history
      where price_history.part_no= a.part_no
      order by valid_from desc
    ) where rownum=1
  )
from  article_table a where rownum < 5

Par ailleurs, vous pouvez vous renseigner sur les fonctions analytiques d'Oracle pour effectuer des requêtes plus simples à cette fin :

http://psoug.org/reference/analytic_functions.html

1voto

Benoit Points 35553

J'essaierais ce qui suit :

select something, somethingelse, last_value(quote_price) over (partition by part_no order by valid_from asc)
  from article_table inner join price_history using (part_no)
 where rownum < 5;

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X