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

SQL Oracle Discussion :

Pb Fonction analytique last_value


Sujet :

SQL Oracle

  1. #1
    McM
    McM est déconnecté
    Expert éminent

    Homme Profil pro
    Développeur Oracle
    Inscrit en
    Juillet 2003
    Messages
    4 580
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Développeur Oracle

    Informations forums :
    Inscription : Juillet 2003
    Messages : 4 580
    Points : 7 740
    Points
    7 740
    Billets dans le blog
    4
    Par défaut Pb Fonction analytique last_value
    en 9i:

    J'ai un problème de compréhension du LAST_VALUE. Il me semblait que c'était la dernière valeur de la partition. Le FIRST_VALUE étant la première.

    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
    WITH t AS (	SELECT 1 AS a, 1 AS b FROM dual 
    			UNION ALL SELECT 1, 2 FROM dual 
    			UNION ALL SELECT 1, 3 FROM dual)
    SELECT 'FIRST', a, b,
    		first_value(b) OVER (PARTITION BY a ORDER BY b) AS B_ASC,
    		first_value(b) OVER (PARTITION BY a ORDER BY b DESC) AS b_desc
    FROM t
    UNION ALL
    SELECT 'LAST', a, b,
    		last_value(b) OVER (PARTITION BY a ORDER BY b),
    		last_value(b) OVER (PARTITION BY a ORDER BY b DESC)
    FROM t
     
    'FIRST'	A	B	B_ASC	B_DESC
    FIRST	1	1	1	3
    FIRST	1	2	1	3
    FIRST	1	3	1	3
    LAST	1	1	1	1
    LAST	1	2	2	2
    LAST	1	3	3	3
    Pour le LAST je suis obligé de mettre une clause de RANGE. Ce qui n'est pas top.
    More Code : More Bugs. Less Code : Less Bugs
    Mon Blog PL/Sql : Fichier Zip / Image BMP / Lire sqliteDB / QRCode et Images PNG ou BMP

  2. #2
    Membre expert

    Homme Profil pro
    Chef de projet en SSII
    Inscrit en
    Janvier 2004
    Messages
    2 862
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Loire Atlantique (Pays de la Loire)

    Informations professionnelles :
    Activité : Chef de projet en SSII
    Secteur : Conseil

    Informations forums :
    Inscription : Janvier 2004
    Messages : 2 862
    Points : 3 609
    Points
    3 609
    Par défaut
    Moi, cela ne me surprend pas plus que cela tu ne définis pas de fenêtrage. Je suppose donc qu'il prend la dernière valeur trouvée jusqu'à la ligne en cours (je n'ai trouvé aucune info dans la doc oracle, c'est juste une analyse personnelle).
    Dès que tu définis un fenêtrage cela fonctionne comme tu t'y attends :
    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
    SQL> WITH t AS ( SELECT 1 AS a, 1 AS b FROM dual 
      2     UNION ALL SELECT 1, 2 FROM dual 
      3     UNION ALL SELECT 1, 3 FROM dual)
      4  SELECT 'FIRST', a, b,
      5    first_value(b) OVER (PARTITION BY a ORDER BY b) AS B_ASC,
      6    first_value(b) OVER (PARTITION BY a ORDER BY b DESC) AS b_desc
      7  FROM t
      8  UNION ALL
      9  SELECT 'LAST', a, b,
     10    last_value(b) OVER (PARTITION BY a ORDER BY b ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING),
     11    last_value(b) OVER (PARTITION BY a ORDER BY b DESC ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING)
     12  FROM t
     13  /
     
    'FIRS          A          B      B_ASC     B_DESC
    ----- ---------- ---------- ---------- ----------
    FIRST          1          1          1          3
    FIRST          1          2          1          3
    FIRST          1          3          1          3
    LAST           1          1          3          1
    LAST           1          2          3          1
    LAST           1          3          3          1
     
    6 ligne(s) sélectionnée(s).
    Un problème sans solution est un problème mal posé

    Merci de poser vos questions sur le forum, je ne réponds pas aux questions posées par MP.

  3. #3
    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
    Points : 1 197
    Points
    1 197
    Par défaut
    Salut,

    Voici les liens qui parlent de l'utilisation ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING
    http://download.oracle.com/docs/cd/B...nctions073.htm
    http://orafaq.com/node/55

  4. #4
    McM
    McM est déconnecté
    Expert éminent

    Homme Profil pro
    Développeur Oracle
    Inscrit en
    Juillet 2003
    Messages
    4 580
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Développeur Oracle

    Informations forums :
    Inscription : Juillet 2003
    Messages : 4 580
    Points : 7 740
    Points
    7 740
    Billets dans le blog
    4
    Par défaut
    Je pensais que
    - Le fenêtrage était fait par le PARTITION BY et que les options ROWS BETWEEN et RANGE BETWEEN étaient des précisions supplémentaires.
    - le LAST_VALUE était comme le MAX()

    Bref, je vais donc continuer à utiliser le FIRST_VALUE ORDER BY DESC

    Je suppose donc qu'il prend la dernière valeur trouvée jusqu'à la ligne en cours
    Oui mais l'order by devrait fonctionner dans ce cas.
    l'exemple du LEAD : Le order by fonctionne.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    WITH t AS (	SELECT 1 AS a, 1 AS b FROM dual 
    			UNION ALL SELECT 1, 2 FROM dual 
    			UNION ALL SELECT 1, 3 FROM dual
    			UNION ALL SELECT 1, 4 FROM dual)
    SELECT a, b,
    		lead(b, 1) OVER (PARTITION BY a ORDER BY b) AS l_asc,
    		lead(b, 1) OVER (PARTITION BY a ORDER BY b DESC) AS l_desc
    FROM t
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    A	B	L_ASC	L_DESC
    1	1	2	
    1	2	3	1
    1	3	4	2
    1	4		3
    More Code : More Bugs. Less Code : Less Bugs
    Mon Blog PL/Sql : Fichier Zip / Image BMP / Lire sqliteDB / QRCode et Images PNG ou BMP

  5. #5
    McM
    McM est déconnecté
    Expert éminent

    Homme Profil pro
    Développeur Oracle
    Inscrit en
    Juillet 2003
    Messages
    4 580
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Développeur Oracle

    Informations forums :
    Inscription : Juillet 2003
    Messages : 4 580
    Points : 7 740
    Points
    7 740
    Billets dans le blog
    4
    Par défaut
    La doc officielle (premier lien) ne donne pas trop d'explication.
    Le second lien est mieux mais :
    Some analytic functions (AVG, COUNT, FIRST_VALUE, LAST_VALUE, MAX, MIN and SUM among the ones we discussed) can take a window clause to further sub-partition the result
    Donc c'est ce que je pensais : La fenêtre c'est le partition by, la sous fenêtre c'est le range.
    More Code : More Bugs. Less Code : Less Bugs
    Mon Blog PL/Sql : Fichier Zip / Image BMP / Lire sqliteDB / QRCode et Images PNG ou BMP

  6. #6
    Membre expert

    Homme Profil pro
    Chef de projet en SSII
    Inscrit en
    Janvier 2004
    Messages
    2 862
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Loire Atlantique (Pays de la Loire)

    Informations professionnelles :
    Activité : Chef de projet en SSII
    Secteur : Conseil

    Informations forums :
    Inscription : Janvier 2004
    Messages : 2 862
    Points : 3 609
    Points
    3 609
    Par défaut
    Citation Envoyé par McM
    Je pensais que
    - Le fenêtrage était fait par le PARTITION BY et que les options ROWS
    Pour moi :
    - le partition by est équivalent au group by.
    - l'option rows définit le type et la précision de la fenêtre (en nombre de lignes)
    (cf. article de Laystar)

    Citation Envoyé par McM
    - le LAST_VALUE était comme le MAX()
    Ah non, c'est la dernière valeur et non la valeur max, ce qui n'a rien à voir.

    Tu noteras que dans la doc oracle, ils indiquent toujours une clause rows, contrairement au lead puisque pour cette fonction tu précises en paramètre la position de lignes à retenir.

    Enfin si tu fais :
    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
    SQL> WITH t AS ( SELECT 1 AS a, 1 AS b FROM dual 
      2     UNION ALL SELECT 1, 2 FROM dual 
      3     UNION ALL SELECT 1, 3 FROM dual)
      4  SELECT 'FIRST', a, b,
      5    first_value(b) OVER (PARTITION BY a ORDER BY b) AS B_ASC,
      6    first_value(b) OVER (PARTITION BY a ORDER BY b DESC) AS b_desc
      7  FROM t
      8  UNION ALL
      9  SELECT 'LAST', a, b,
     10    last_value(b) OVER (PARTITION BY a ORDER BY b ROWS BETWEEN UNBOUNDED PRECEDING AND 0 FOLLOWING),
     11    last_value(b) OVER (PARTITION BY a ORDER BY b DESC ROWS BETWEEN UNBOUNDED PRECEDING AND 0 FOLLOWING)
     12  FROM t
     13  /
     
    'FIRS          A          B      B_ASC     B_DESC
    ----- ---------- ---------- ---------- ----------
    FIRST          1          1          1          3
    FIRST          1          2          1          3
    FIRST          1          3          1          3
    LAST           1          1          1          1
    LAST           1          2          2          2
    LAST           1          3          3          3
     
    6 ligne(s) sélectionnée(s).
    Ce qui semble corroborer ce que je pensais.
    Un problème sans solution est un problème mal posé

    Merci de poser vos questions sur le forum, je ne réponds pas aux questions posées par MP.

  7. #7
    McM
    McM est déconnecté
    Expert éminent

    Homme Profil pro
    Développeur Oracle
    Inscrit en
    Juillet 2003
    Messages
    4 580
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Développeur Oracle

    Informations forums :
    Inscription : Juillet 2003
    Messages : 4 580
    Points : 7 740
    Points
    7 740
    Billets dans le blog
    4
    Par défaut
    Ce qui semble corroborer ce que je pensais
    Que pour un même fenêtrage, le ORDER BY n'a aucune influence ?

    Sans ORDER BY dans le OVER, le résultat est bon, suivant le tri du SELECT
    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
    WITH t AS ( SELECT 1 AS a, 1 AS b FROM dual 
           UNION ALL SELECT 1, 2 FROM dual 
           UNION ALL SELECT 1, 3 FROM dual
    		)
    SELECT a, b,
         last_value(b) OVER (PARTITION BY a) l1
    FROM t
    ORDER BY a, b (ASC/DESC)
     
     
    A	B	L1_ASC
    1	1	3
    1	2	3
    1	3	3
     
    A	B	L1_DESC
    1	3	1
    1	2	1
    1	1	1
    Donc je comprend que le LAST_VALUE n'a pas le même comportement que les autres fonctions à propos du ORDER BY de sa clause.
    Et qu'il faut donc utiliser le ROW UNBOUNDED.
    More Code : More Bugs. Less Code : Less Bugs
    Mon Blog PL/Sql : Fichier Zip / Image BMP / Lire sqliteDB / QRCode et Images PNG ou BMP

  8. #8
    Membre expert

    Homme Profil pro
    Chef de projet en SSII
    Inscrit en
    Janvier 2004
    Messages
    2 862
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Loire Atlantique (Pays de la Loire)

    Informations professionnelles :
    Activité : Chef de projet en SSII
    Secteur : Conseil

    Informations forums :
    Inscription : Janvier 2004
    Messages : 2 862
    Points : 3 609
    Points
    3 609
    Par défaut
    Citation Envoyé par McM
    Et qu'il faut donc utiliser le ROW UNBOUNDED.
    C'est surtout cela qu'il faut retenir, je crois !

    Je vais essayer d'être clair (c'est pas gagné) :
    Pour mois il tient compte du order by mais uniquement dans le fenêtrage global (j'entends par là partition by et rows) : cf. mon 1è post.

    Par contre si tu ne définis pas de "rows", il ne ramène que la dernière valeur entre la première ligne traitée et la ligne courante.

    Et ce qui est très marrant, c'est suivant l'ordre des colonnes où tu définis le tri, il ne ramène pas la même chose :
    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
    SQL> WITH t AS ( SELECT 1 AS a, 1 AS b FROM dual
      2     UNION ALL SELECT 1, 4 FROM dual
      3     UNION ALL SELECT 1, 2 FROM dual)
      4  SELECT 'LAST', a, b,
      5    last_value(b) OVER (PARTITION BY a ORDER BY b) b_asc,
      6    last_value(b) OVER (PARTITION BY a ORDER BY b desc) b_desc
      7  FROM t
      8  /
     
    'LAS          A          B      B_ASC     B_DESC
    ---- ---------- ---------- ---------- ----------
    LAST          1          1          1          1
    LAST          1          2          2          2
    LAST          1          4          4          4
     
    SQL> WITH t AS ( SELECT 1 AS a, 1 AS b FROM dual
      2     UNION ALL SELECT 1, 4 FROM dual
      3     UNION ALL SELECT 1, 2 FROM dual)
      4  SELECT 'LAST', a, b,
      5    last_value(b) OVER (PARTITION BY a ORDER BY b DESC) b_desc,
      6    last_value(b) OVER (PARTITION BY a ORDER BY b) b_asc
      7  FROM t
      8  /
     
    'LAS          A          B     B_DESC      B_ASC
    ---- ---------- ---------- ---------- ----------
    LAST          1          4          4          4
    LAST          1          2          2          2
    LAST          1          1          1          1
    Un problème sans solution est un problème mal posé

    Merci de poser vos questions sur le forum, je ne réponds pas aux questions posées par MP.

  9. #9
    McM
    McM est déconnecté
    Expert éminent

    Homme Profil pro
    Développeur Oracle
    Inscrit en
    Juillet 2003
    Messages
    4 580
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Développeur Oracle

    Informations forums :
    Inscription : Juillet 2003
    Messages : 4 580
    Points : 7 740
    Points
    7 740
    Billets dans le blog
    4
    Par défaut
    En fait c'est en fonction du tri du SELECT.
    S'il n'y a pas de tri, le tri de la première fct analytique implique le tri du select
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    WITH t AS ( SELECT 1 AS a, 1 AS b FROM dual
           UNION ALL SELECT 1, 4 FROM dual
           UNION ALL SELECT 1, 2 FROM dual)
        SELECT a, b,
          last_value(b) OVER (PARTITION BY a ORDER BY b DESC) b_desc,
          last_value(b) OVER (PARTITION BY a ORDER BY b) b_asc
        FROM t
    	ORDER BY a, b  
     
    A	B	B_DESC	B_ASC
    1	1	1	1
    1	2	2	2
    1	4	4	4
    More Code : More Bugs. Less Code : Less Bugs
    Mon Blog PL/Sql : Fichier Zip / Image BMP / Lire sqliteDB / QRCode et Images PNG ou BMP

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. [SQL / PL/SQL] fonction analytique last_value
    Par Nounoursonne dans le forum SQL
    Réponses: 7
    Dernier message: 23/08/2007, 21h18
  2. [SQL / PL/SQL] fonction analytique last_value
    Par Nounoursonne dans le forum Oracle
    Réponses: 7
    Dernier message: 23/08/2007, 21h18
  3. Réponses: 3
    Dernier message: 24/11/2005, 12h19
  4. Réponses: 7
    Dernier message: 21/11/2005, 14h21
  5. Réponses: 4
    Dernier message: 18/08/2005, 16h11

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