IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

PL/SQL Oracle Discussion :

construction d'une req


Sujet :

PL/SQL Oracle

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre confirmé
    Inscrit en
    Mars 2009
    Messages
    86
    Détails du profil
    Informations forums :
    Inscription : Mars 2009
    Messages : 86
    Par défaut construction d'une req
    Bonjour,

    J'ai une table qui contient deux col :
    + date traitement : qui est date du jour
    + valeur : prix du jour d'un produit X

    Chaque jour une ligne est insérée dans la table avec la date du jour et prix du produit X.

    Je veux faire une req pour récupérer sur les 20 dérniers jours glissants les différents prix du produit.
    Ex : 01/07/2009 12
    02/07/2009 12
    03/07/2009 10
    04/07/2009 10
    05/07/2009 5
    06/07/2009 4

    Le resultat attendu :
    01/07/2009 12
    03/07/2009 10
    05/07/2009 5
    06/07/2009 4

    pourriez vous me dire comment je peux me prendre?

    Merci

  2. #2
    Membre Expert Avatar de fatsora
    Profil pro
    Inscrit en
    Février 2006
    Messages
    1 103
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2006
    Messages : 1 103
    Par défaut
    Bonjour,

    avec fonctions ananytiques

    http://lalystar.developpez.com/fonctionsAnalytiques/

    Code sql : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    /* SQL formatted with free online SQLinForm Engine Release 4.6.14 */
     
    WITH datas AS
         (SELECT to_date ('01/07/2009','DD/MM/YYYY') jour,
                 12                                  nbr
         FROM    dual
     
         UNION
     
         SELECT to_date ('02/07/2009','DD/MM/YYYY') ,
                12
         FROM   dual
     
         UNION
     
         SELECT to_date ('03/07/2009','DD/MM/YYYY') ,
                10
         FROM   dual
     
         UNION
     
         SELECT to_date ('04/07/2009','DD/MM/YYYY') ,
                10
         FROM   dual
     
         UNION
     
         SELECT to_date ('05/07/2009','DD/MM/YYYY') ,
                5
         FROM   dual
     
         UNION
     
         SELECT to_date ('06/07/2009','DD/MM/YYYY') ,
                4
         FROM   dual
         )
    SELECT DISTINCT first_value(jour) over (partition BY nbr ORDER BY jour ) jr,
                    nbr
    FROM            datas
    ORDER BY        jr ;

  3. #3
    Membre émérite
    Profil pro
    Inscrit en
    Août 2008
    Messages
    861
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2008
    Messages : 861
    Par défaut
    Bonjour,

    Cette solution fonctionne bien pour l'exemple proposé par radahm, mais ne renverra pas un changement de prix qui revient à une ancienne valeur, par exemple :
    01/07/2009 12
    02/07/2009 12
    03/07/2009 10
    04/07/2009 10
    05/07/2009 12
    06/07/2009 4
    En fonction du besoin, on peut utiliser LAG, qui permettra de récupérer le prix précédent, et de ne selectionner que les lignes où prix_courant <> prix_precedent :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
     
    SELECT 
           prix.date_traitement,
           prix.prix_courant as prix
    FROM (SELECT 
                 date_traitement,	
                 prix as prix_courant,
                 lag(prix) over (order by date_traitement) as prix_precedent
          FROM TablePrix
          WHERE TablePrix.date_traitement >= sysdate-20	
         ) prix
    WHERE prix.prix_courant <> prix_precedent OR prix_precedent IS NULL   
    ORDER BY prix.date_traitement
    Je suppose aussi qu'il n'y a pas une table par produit, et que par conséquent il y a sans doute un identifiant produit quelque part, donc ces requêtes sont probablement à adapter.

  4. #4
    Membre Expert Avatar de fatsora
    Profil pro
    Inscrit en
    Février 2006
    Messages
    1 103
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2006
    Messages : 1 103
    Par défaut
    Bien vu pour le LAG ...

    Mon idée c'est surtout que la prochaine fois notre ami puisse se servir des fonctions analytique a condition que version Oracle >= 8I

    apres si l'exemple ne reflete pas les données .... il y a LAG

  5. #5
    Rédacteur

    Homme Profil pro
    Développeur et DBA Oracle
    Inscrit en
    Octobre 2006
    Messages
    878
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Algérie

    Informations professionnelles :
    Activité : Développeur et DBA Oracle

    Informations forums :
    Inscription : Octobre 2006
    Messages : 878
    Par défaut
    Ou
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
     
    WITH datas AS
         (SELECT TO_DATE ('01/07/2009', 'DD/MM/YYYY') jour, 12 nbr
            FROM DUAL
          UNION
          SELECT TO_DATE ('02/07/2009', 'DD/MM/YYYY'), 12
            FROM DUAL
          UNION
          SELECT TO_DATE ('03/07/2009', 'DD/MM/YYYY'), 10
            FROM DUAL
          UNION
          SELECT TO_DATE ('04/07/2009', 'DD/MM/YYYY'), 10
            FROM DUAL
          UNION
          SELECT TO_DATE ('05/07/2009', 'DD/MM/YYYY'), 5
            FROM DUAL
          UNION
          SELECT TO_DATE ('06/07/2009', 'DD/MM/YYYY'), 4
            FROM DUAL)
    SELECT   MIN (jour)KEEP (DENSE_RANK FIRST ORDER BY jour) jr, nbr
        FROM datas
    GROUP BY nbr
    ORDER BY jr;
     
     
    JR                NBR
    ---------- ----------
    2009-07-01         12
    2009-07-03         10
    2009-07-05          5
    2009-07-06          4
     
     
    4 rows selected.

  6. #6
    Membre confirmé
    Inscrit en
    Mars 2009
    Messages
    86
    Détails du profil
    Informations forums :
    Inscription : Mars 2009
    Messages : 86
    Par défaut
    Bonjour,

    Merci pour vos réponse,

    j'ai utilisé la sol proposé par 'Snipah' (Effectivement dans ma table j'ai un Id produit), cela fonctionne bien dans quelques cas, mais j'arrive pas à la faire fonctionner dans le cas suivant :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     
    29/06/2009 
    01/07/2009 12
    02/07/2009 12
    03/07/2009 10
    04/07/2009 10
    05/07/2009 12
    06/07/2009
    enfaite je ne récupère pas la dernière ligne '06/07/2009 '
    j'ai modifié la req en mettant
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    prix.prix_courant <> prix_precedent OR (prix_precedent IS NULL and prix_courant is not null) OR (prix_precedent IS NOT NULL and prix_courant is null)
    sans avoir la bonne reponse!!!
    sauriez vous d'où vient le pb?

    Merci

  7. #7
    Membre émérite
    Profil pro
    Inscrit en
    Août 2008
    Messages
    861
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2008
    Messages : 861
    Par défaut
    Remplacez les valeurs NULL par 0 par exemple, lors de la comparaison :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    SELECT 
           prix.date_traitement,
           prix.prix_courant AS prix
    FROM (SELECT 
                 date_traitement,	
                 prix AS prix_courant,
                 lag(prix) over (ORDER BY date_traitement) AS prix_precedent
          FROM TablePrix
          WHERE TablePrix.date_traitement >= sysdate-20	
         ) prix
    WHERE coalesce(prix.prix_courant,0) <> coalesce(prix_precedent,0)
    ORDER BY prix.date_traitement

  8. #8
    Membre confirmé
    Inscrit en
    Mars 2009
    Messages
    86
    Détails du profil
    Informations forums :
    Inscription : Mars 2009
    Messages : 86
    Par défaut
    Enfaite je compare le changement du prix et d'autres caracteristiques de type String. Dans ce cas le coalesce ne fonctionne pas.
    Y à t il un moyen de faire autrement?

    Merci

  9. #9
    Modérateur
    Avatar de Waldar
    Homme Profil pro
    Sr. Specialist Solutions Architect @Databricks
    Inscrit en
    Septembre 2008
    Messages
    8 454
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 47
    Localisation : France, Val de Marne (Île de France)

    Informations professionnelles :
    Activité : Sr. Specialist Solutions Architect @Databricks
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2008
    Messages : 8 454
    Par défaut
    Je vous propose la requête suivante, issue d'un des vainqueurs du challenge TSQL #9 (lien en anglais) :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    WITH DATAS AS
    (
    SELECT DATE '2009-06-29' AS JOUR, NULL AS PRIX FROM DUAL UNION ALL
    SELECT DATE '2009-07-01'        , 12           FROM DUAL UNION ALL
    SELECT DATE '2009-07-02'        , 12           FROM DUAL UNION ALL
    SELECT DATE '2009-07-03'        , 10           FROM DUAL UNION ALL
    SELECT DATE '2009-07-04'        , 10           FROM DUAL UNION ALL
    SELECT DATE '2009-07-05'        , 12           FROM DUAL UNION ALL
    SELECT DATE '2009-07-06'        , NULL         FROM DUAL
    ),
       ID_DATAS AS
    (   
    SELECT
        JOUR,
        PRIX,
        ROW_NUMBER() OVER(ORDER BY JOUR ASC) - -- AS ID,
        ROW_NUMBER() OVER(PARTITION BY PRIX ORDER BY JOUR ASC) AS G_ID
    FROM DATAS
    )
      SELECT MIN(JOUR) AS JOUR, PRIX
        FROM ID_DATAS
    GROUP BY G_ID, PRIX
    ORDER BY G_ID ASC;
     
    JOUR                      PRIX                   
    ------------------------- ---------------------- 
    2009-06-29                                       
    2009-07-01                12                     
    2009-07-03                10                     
    2009-07-05                12                     
    2009-07-06
    Si vous comparez sur plus d'éléments que le prix, il suffit de les ajouter dans le partition by du second row_number() de la requête.

  10. #10
    Membre confirmé
    Inscrit en
    Mars 2009
    Messages
    86
    Détails du profil
    Informations forums :
    Inscription : Mars 2009
    Messages : 86
    Par défaut
    peux-tu détailler la sol? j'ai du mal à comprendre chaque partie de la req

    Merci

Discussions similaires

  1. De l'aide pour une req?? ce serait gentil :)
    Par **jouly** dans le forum Langage SQL
    Réponses: 6
    Dernier message: 09/02/2005, 14h01
  2. lock conflict sur une req select
    Par veronique dans le forum Connexion aux bases de données
    Réponses: 6
    Dernier message: 02/02/2005, 09h12
  3. construction d'une classe
    Par r0d dans le forum C++
    Réponses: 10
    Dernier message: 16/09/2004, 17h35
  4. erreur au lancement d'une req Oracle (SP2-0552)
    Par etham dans le forum Administration
    Réponses: 5
    Dernier message: 16/04/2004, 16h23
  5. Réponses: 4
    Dernier message: 03/03/2004, 11h04

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo