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 :

[Info] Produit cumulative en sql


Sujet :

SQL Oracle

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    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 [Info] Produit cumulative en sql
    Salut,

    Je veux partager ce script avec vous.

    Salim.

    Solution avec Model clause
    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
     
    WITH t AS
         (SELECT 1 ID, 1 val
            FROM DUAL
          UNION ALL
          SELECT 2 ID, 2 val
            FROM DUAL
          UNION ALL
          SELECT 3 ID, 3 val
            FROM DUAL
          UNION ALL
          SELECT 4 ID, 4 val
            FROM DUAL)
    select id,val,cumulative_product
    from t
    model 
    dimension by(id)
    measures( val,1 cumulative_product)
    (cumulative_product[any]order by id asc=nvl(cumulative_product[cv()-1],1)*val[cv()]);
     
     
            ID        VAL CUMULATIVE_PRODUCT
    ---------- ---------- ------------------
             1          1                  1
             2          2                  2
             3          3                  6
             4          4                 24
     
     
    4 rows selected.
    Solution sans model clause( pour des valeurs positives)
    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
     
    WITH t AS
         (SELECT 1 ID, 1 val
            FROM DUAL
          UNION ALL
          SELECT 2 ID, 2 val
            FROM DUAL
          UNION ALL
          SELECT 3 ID, 3 val
            FROM DUAL
          UNION ALL
          SELECT 4 ID, 4 val
            FROM DUAL)
    SELECT ID, val,
           EXP (SUM (LN (val)) OVER (PARTITION BY NULL ORDER BY ID)
               ) cumulative_product
      FROM t;
     
     
            ID        VAL CUMULATIVE_PRODUCT
    ---------- ---------- ------------------
             1          1                  1
             2          2                  2       -->exp (ln(1)+ln(2)= exp(ln(1))*exp(ln(2))=1*2=2
             3          3         6.00000000 --> exp (ln(1)+ln(2)+ln(3))= exp(ln(1))*exp(ln(2))*exp(ln(3))=1*2*3=6
             4          4         24.0000000 --> exp (ln(1)+ln(2)+ln(3)+ln(4))=exp(ln(1))*exp(ln(2))*exp(ln(3))*exp(ln(4))=1*2*3*4=24
     
     
    4 rows selected.
    Solution sans model avec des valeurs postives et négatives
    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
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
     
    WITH t AS
         (SELECT 1 AS ID, 1 AS val
            FROM DUAL
          UNION ALL
          SELECT 2, -2
            FROM DUAL
          UNION ALL
          SELECT 3, 3
            FROM DUAL
          UNION ALL
          SELECT 4, 4
            FROM DUAL
          UNION ALL
          SELECT 5, 5
            FROM DUAL
          UNION ALL
          SELECT 6, -4
            FROM DUAL)
    SELECT ID, val,
             EXP
                (SUM (LN (ABS (val))) OVER (PARTITION BY NULL ORDER BY ID)
                )
           * CASE
                WHEN MOD
                       (COUNT (CASE
                                  WHEN SIGN (val) = -1
                                     THEN 1
                               END) OVER (PARTITION BY NULL ORDER BY ID),
                        2
                       ) = 0
                   THEN 1
                ELSE -1
             END cumulative_product
      FROM t;
     
     
            ID        VAL CUMULATIVE_PRODUCT
    ---------- ---------- ------------------
             1          1                  1
             2         -2                 -2
             3          3         -6.0000000
             4          4         -24.000000
             5          5         -120.00000
             6         -4         480.000000

  2. #2
    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
    Hello salim,


    Je m'en étais servi de la seconde méthode pour calculer les factoriels pour le NoCOUG challenge.

    J'avais rajouté un arrondi pour éviter les erreurs de précisions induis par LN et de EXP :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    WITH fact AS
    (
    SELECT 0 AS l, 1 AS f
    FROM DUAL
    UNION ALL
    SELECT
        LEVEL AS l,
        ROUND( EXP( SUM (LN (LEVEL)) OVER (ORDER BY LEVEL ASC))) AS f
    FROM DUAL
    CONNECT BY LEVEL <= 83
    )
    select * from fact
    Au-dessus de 83 ça plante par contre, et côté arrondi ce n'est pas toujours parfait !

  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
    Par défaut
    Citation Envoyé par Waldar Voir le message
    Hello salim,
    Au-dessus de 83 ça plante par contre, et côté arrondi ce n'est pas toujours parfait !
    Salut waldar,

    Oui, t'as raison.

    Salim

  4. #4
    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
    Citation Envoyé par Waldar Voir le message
    Hello salim,


    Je m'en étais servi de la seconde méthode pour calculer les factoriels pour le NoCOUG challenge.

    J'avais rajouté un arrondi pour éviter les erreurs de précisions induis par LN et de EXP :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    WITH fact AS
    (
    SELECT 0 AS l, 1 AS f
    FROM DUAL
    UNION ALL
    SELECT
        LEVEL AS l,
        ROUND( EXP( SUM (LN (LEVEL)) OVER (ORDER BY LEVEL ASC))) AS f
    FROM DUAL
    CONNECT BY LEVEL <= 83
    )
    select * from fact
    Au-dessus de 83 ça plante par contre, et côté arrondi ce n'est pas toujours parfait !
    Salut Waldar,

    On peut remédier à cette situation:

    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
    35
    36
    37
    38
    39
    40
    41
    42
    43
     
    DROP TABLE DATA;
     
    CREATE TABLE DATA
    (
      ID   NUMBER,
      val  BINARY_DOUBLE
    );
     
    INSERT INTO DATA
       (SELECT 0 AS l, 1 AS f
          FROM DUAL
        UNION ALL
        SELECT     LEVEL AS l, LEVEL f
              FROM DUAL
        CONNECT BY LEVEL <= 300);
     
     
    SELECT ID AS l, EXP (SUM (LN (val)) OVER (ORDER BY ID ASC)) val
      FROM DATA;
     
           ...................................................................
           ...................................................................
           ...................................................................
           ...................................................................
           163                                         2.00440157654583E291
           164                                         3.28721858553507E293
           165                                          5.4239106661326E295
           166                                         9.00369170577961E297
           167                                         1.50361651486524E300
     
             L                                                          VAL
    ---------- ------------------------------------------------------------
           168                                         2.52607574497356E302
           169                                          4.2690680090055E304
           170                                         7.25741561530971E306
           171                                                          INF
           172                                                          INF
           173                                                          INF
           174                                                          INF
           175                                                          INF
           ...................................................................
           ....................................................................

  5. #5
    Expert confirmé Avatar de mnitu
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Octobre 2007
    Messages
    5 611
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Marne (Champagne Ardenne)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Octobre 2007
    Messages : 5 611
    Par défaut
    Salut Salim11

    Je te propose encore une solution

    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
     
    Connected to Oracle9i Enterprise Edition Release 9.2.0.7.0 
    Connected as mni
     
    SQL> 
    SQL> WITH t AS
      2       (SELECT 1 ID, 1 val
      3          FROM DUAL
      4        UNION ALL
      5        SELECT 2 ID, 2 val
      6          FROM DUAL
      7        UNION ALL
      8        SELECT 3 ID, 3 val
      9          FROM DUAL
     10        UNION ALL
     11        SELECT 4 ID, 4 val
     12          FROM DUAL)
     13  SELECT id,val,cumulativeproduct(val) over(order by id)
     14  FROM t
     15  /
     
            ID        VAL CUMULATIVEPRODUCT(VAL)OVER(ORD
    ---------- ---------- ------------------------------
             1          1                              1
             2          2                              2
             3          3                              6
             4          4                             24
     
    SQL>

  6. #6
    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
    Salut mnitu;


    Bizarre, il ne reconnait pas cette fonction, est ce que c’est une fonction non documentée d’oracle.


    Salim.
    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
     
    SQL> select * from v$version;
     
    BANNER
    ----------------------------------------------------------------
    Oracle Database 10g Enterprise Edition Release 10.2.0.3.0 - 64bi
    PL/SQL Release 10.2.0.3.0 - Production
    CORE    10.2.0.3.0      Production
    TNS for Linux: Version 10.2.0.3.0 - Production
    NLSRTL Version 10.2.0.3.0 - Production
     
    SQL> select id,cumulativeproduct(val)over(order by id) from data;
    select id,cumulativeproduct(val)over(order by id) from data
              *
    ERREUR à la ligne 1 :
    ORA-00904: "CUMULATIVEPRODUCT" : identificateur non valide
     
     
    SQL>

  7. #7
    Expert confirmé Avatar de mnitu
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Octobre 2007
    Messages
    5 611
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Marne (Champagne Ardenne)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Octobre 2007
    Messages : 5 611
    Par défaut
    Oui, j'ai triché un peu mais je trouve que la solution est assez élégante est simple:

    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
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
     
    create type CumulativeProductImpl as object
    (
      prod NUMBER,  
      static function ODCIAggregateInitialize(sctx IN OUT CumulativeProductImpl) 
        return number,
      member function ODCIAggregateIterate(self IN OUT CumulativeProductImpl, 
        value IN number) return number,
      member function ODCIAggregateTerminate(self IN CumulativeProductImpl, 
        returnValue OUT number, flags IN number) return number,
      member function ODCIAggregateMerge(self IN OUT CumulativeProductImpl, 
        ctx2 IN CumulativeProductImpl) return number
    );
    /
    create or replace type body CumulativeProductImpl is 
    static function ODCIAggregateInitialize(sctx IN OUT CumulativeProductImpl) 
    return number is 
    begin
      sctx := CumulativeProductImpl(1);
      return ODCIConst.Success;
    end;
     
    member function ODCIAggregateIterate(self IN OUT CumulativeProductImpl, value IN number) return number is
    begin
      self.prod := self.prod * value;
      return ODCIConst.Success;
    end;
     
    member function ODCIAggregateTerminate(self IN CumulativeProductImpl, returnValue OUT number, flags IN number) return number is
    begin
      returnValue := self.prod;
      return ODCIConst.Success;
    end;
     
    member function ODCIAggregateMerge(self IN OUT CumulativeProductImpl, ctx2 IN CumulativeProductImpl) return number is
    begin
      self.prod := self.prod * ctx2.prod;
      return ODCIConst.Success;
    end;
    end;
    /
     
    CREATE FUNCTION CumulativeProduct (input NUMBER) RETURN NUMBER 
    PARALLEL_ENABLE AGGREGATE USING CumulativeProductImpl;
    /
    A voir User-Defined Aggregates

Discussions similaires

  1. [MySQL] Affichage de fiche produit en PHP/SQL
    Par quaresma dans le forum PHP & Base de données
    Réponses: 10
    Dernier message: 09/03/2011, 00h48
  2. Besoin d'infos pour une requête SQL
    Par jeanmarc1234 dans le forum Langage SQL
    Réponses: 11
    Dernier message: 07/03/2008, 18h47
  3. ! Somme Cumulative en SQL !
    Par dom283 dans le forum Langage SQL
    Réponses: 3
    Dernier message: 16/03/2007, 18h25
  4. [ADO.Net][C#] Comment récupérer des infos d'une table SQL ?
    Par lamojuli dans le forum Accès aux données
    Réponses: 2
    Dernier message: 11/01/2006, 16h00
  5. Réponses: 3
    Dernier message: 21/06/2005, 10h23

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