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 :

Plusieurs SUM sur une même table


Sujet :

SQL Oracle

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre averti
    Homme Profil pro
    Administrateur de base de données
    Inscrit en
    Avril 2011
    Messages
    16
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 41
    Localisation : France, Cher (Centre)

    Informations professionnelles :
    Activité : Administrateur de base de données
    Secteur : Service public

    Informations forums :
    Inscription : Avril 2011
    Messages : 16
    Par défaut Plusieurs SUM sur une même table
    Bonjour,

    J'ai fait plusieurs recherches sur le forum, mais je n'arrive pas à trouver de sujet similaire alors je me lance.

    Tout d'abord, la structure de mes tables versions simplifiées pour expliquer mon problème :
    - occupation(numero_occupation,individu,type_occupation#,duree)
    - type_occupation(type_occupation,libelle_occupation)

    La table type_occupation contient une liste de nomenclature, celles qui m'intéressent :
    1-Heures supplémentaires
    2-Récup heures supp.

    Et dans la table occupation, j'ai un enregistrement par individu pour chaque type occupation et par occupation.
    Par exemple pour l'individu JEAN j'aurais autant d'enregistrements avec un type_occupation=1 (heures supp) qu'il n'en a fait réellement

    589-JEAN-1-120
    590-JEAN-1-30
    591-JEAN-1-15

    592-JEAN-2-30
    593-JEAN-2-45

    Durée en minutes.
    Maintenant mon problème, je souhaiterais avec un select pouvoir cumuler la somme des heures supp, puis la somme des congés compensateurs sur une même ligne pour chaque individu.
    Dans l'exemple du dessus, je voudrais pouvoir avoir :

    JEAN - Heures supp:165minutes - Récup : 75minutes - Reste:90minutes
    FRED - ..................

    J'ai tenté avec sum(duree) over partition by également en faisant deux fois appels à ma table occupation avec des alias différents, mais que nenni ! Je bloque depuis un moment dessus et je n'arrive pas à trouver de solution, si ce n'est la solution pl_sql mais j'ai par habitude de créer mes requètes par des vues qui sont plus simples pour mes collègues pour ré-extraire les infos actualisées en temps réel.

    Toute proposition est la bienvenue, et désolé si s'est une question de newbie :/
    Merci à tous.

    Frédéric.

  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
    Vous cherchez à effectuer un PIVOT, on le fait ainsi :
    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
    With type_occupation as
    (
    select 1 as type_occupation, 'Heures supplémentaires' as libelle_occupation from dual union all
    select 2                   , 'Récup heures supp.'                           from dual
    )
      ,  occupation as
    (
    select 589 as numero_occupation, 'JEAN' as individu, 1 as type_occupation, 120 as duree from dual union all
    select 590                     , 'JEAN'            , 1                   ,  30          from dual union all
    select 591                     , 'JEAN'            , 1                   ,  15          from dual union all
    select 592                     , 'JEAN'            , 2                   ,  30          from dual union all
    select 593                     , 'JEAN'            , 2                   ,  45          from dual
    )
      select occ.individu,
             sum(case toc.type_occupation when 1 then occ.duree end) as heures_suppl,
             sum(case toc.type_occupation when 2 then occ.duree end) as heures_recup,
             sum(case toc.type_occupation when 1 then occ.duree end) -
             sum(case toc.type_occupation when 2 then occ.duree end) as restes_a_recup
        from occupation occ
             inner join type_occupation toc
               on toc.type_occupation = occ.type_occupation
       where toc.type_occupation in (1, 2)
    group by occ.individu;
     
    INDIVIDU HEURES_SUPPL HEURES_RECUP RESTES_A_RECUP
    -------- ------------ ------------ --------------
    JEAN              165           75             90

  3. #3
    Membre averti
    Homme Profil pro
    Administrateur de base de données
    Inscrit en
    Avril 2011
    Messages
    16
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 41
    Localisation : France, Cher (Centre)

    Informations professionnelles :
    Activité : Administrateur de base de données
    Secteur : Service public

    Informations forums :
    Inscription : Avril 2011
    Messages : 16
    Par défaut
    Merci pour cette réponse aussi rapide, je tente depuis ce midi de mettre en application l'exemple sur ma base réelle mais sans succès :s

    J'ai finalement repris le principe de ton exemple, deux requêtes et une troisième pour fusionner les résultats et effectuer le calcul du solde, ce qui me donne donc 3 vues. Moins propre que ce que j'aurais souhaité, mais là clairement, je pense pas avoir les compétences requises :/

    A moins que quelqu'un ne sache retranscrire mes requêtes :

    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
     
    select 
    distinct
    ind.no_individu as numero
    ,ind.nom_affichage as Nom
    ,ind.prenom_affichage as Prénom
    ,str.ll_structure as Service
    ,decode(occ.type,11,'Congés compensateurs',12,'Heures supplémentaires',occ.type) as Type
    ,sum(occ.duree) as dureeMinute
    ,trunc(sum(occ.duree)/60) || 'h' || decode(mod(sum(occ.duree),60),0,'00',1,'01',2,'02',3,'03',4,'04',5,'05',6,'06',7,'07',8,'08',9,'09',mod(sum(occ.duree),60)) as dureeHeure
     
    from
    grhum.individu_ulr ind
    ,mangue.affectation aff
    ,grhum.structure_ulr str
    ,conges.plng_per_aff_ann pan
    ,conges.plng_aff_ann aan
    ,conges.plng_occ occ
     
    where ind.no_individu=aff.no_dossier_pers
    -- Structures et affectations
    and aff.c_structure=str.c_structure
    and aff.d_deb_affectation <= (select sysdate from dual)
    and (aff.d_fin_affectation >= (select sysdate from dual) or aff.d_fin_affectation is null)
    and aff.tem_valide='O'
    -- Planning
    and aff.no_seq_affectation=pan.oid_affectation
    and pan.oid_aff_ann=aan.oid
     
    -- Heures supplémentaires 
    and aan.oid=occ.oid_aff_ann
    -- Etat validé
    and occ.status=0
    -- Sur du planning réél
    and occ.flg_nature='R'
    and occ.type in('12') 
     
    group by ind.no_individu, ind.nom_affichage, ind.prenom_affichage, str.ll_structure, decode(occ.type,11,'Congés compensateurs',12,'Heures supplémentaires',occ.type) 
    order by ind.nom_affichage, ind.prenom_affichage
    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
     
    select 
    distinct
    ind.no_individu as numero
    ,ind.nom_affichage as Nom
    ,ind.prenom_affichage as Prénom
    ,str.ll_structure as Service
    ,decode(occ.type,11,'Congés compensateurs',12,'Heures supplémentaires',occ.type) as Type
    ,sum(occ.duree) as dureeMinute
    ,trunc(sum(occ.duree)/60) || 'h' || decode(mod(sum(occ.duree),60),0,'00',1,'01',2,'02',3,'03',4,'04',5,'05',6,'06',7,'07',8,'08',9,'09',mod(sum(occ.duree),60)) as dureeHeure
     
    from
    grhum.individu_ulr ind
    ,mangue.affectation aff
    ,grhum.structure_ulr str
    ,conges.plng_per_aff_ann pan
    ,conges.plng_aff_ann aan
    ,conges.plng_occ occ
     
    where ind.no_individu=aff.no_dossier_pers
    -- Structures et affectations
    and aff.c_structure=str.c_structure
    and aff.d_deb_affectation <= (select sysdate from dual)
    and (aff.d_fin_affectation >= (select sysdate from dual) or aff.d_fin_affectation is null)
    and aff.tem_valide='O'
    -- Planning
    and aff.no_seq_affectation=pan.oid_affectation
    and pan.oid_aff_ann=aan.oid
     
    -- Heures supplémentaires 
    and aan.oid=occ.oid_aff_ann
    -- Etat validé
    and occ.status=0
    -- Sur du planning réél
    and occ.flg_nature='R'
    and occ.type in('11') 
     
    group by ind.no_individu, ind.nom_affichage, ind.prenom_affichage, str.ll_structure, decode(occ.type,11,'Congés compensateurs',12,'Heures supplémentaires',occ.type) 
    order by ind.nom_affichage, ind.prenom_affichage
    Et celle qui fusionne :

    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
     
     
    select 
    distinct
    ind.no_individu as numero
    ,ind.nom_affichage as Nom
    ,ind.prenom_affichage as Prénom
    ,str.ll_structure as Service
    ,replace(trunc(decode(h.dureeminute,'',0,h.dureeminute)/60) || 'h' || decode(mod(decode(h.dureeminute,'',0,h.dureeminute),60),0,'00',1,'01',2,'02',3,'03',4,'04',5,'05',6,'06',7,'07',8,'08',9,'09',mod(decode(h.dureeminute,'',0,h.dureeminute),60)),'h-','h') as HeureSupp
    ,replace(trunc(decode(c.dureeminute,'',0,c.dureeminute)/60) || 'h' || decode(mod(decode(c.dureeminute,'',0,c.dureeminute),60),0,'00',1,'01',2,'02',3,'03',4,'04',5,'05',6,'06',7,'07',8,'08',9,'09',mod(decode(c.dureeminute,'',0,c.dureeminute),60)),'h-','h') as CongesComp
    ,replace(trunc((decode(h.dureeminute,'',0,h.dureeminute) + decode(c.dureeminute,'',0,c.dureeminute))/60) || 'h' || decode(mod((decode(h.dureeminute,'',0,h.dureeminute) + decode(c.dureeminute,'',0,c.dureeminute)),60),0,'00',1,'01',2,'02',3,'03',4,'04',5,'05',6,'06',7,'07',8,'08',9,'09',mod((decode(h.dureeminute,'',0,h.dureeminute) + decode(c.dureeminute,'',0,c.dureeminute)),60)),'h-','h') as Solde
     
    from 
    grhum.individu_ulr ind
    ,mangue.affectation aff
    ,grhum.structure_ulr str
    ,conges.plng_per_aff_ann pan
    ,ensib_hsupp h
    ,ensib_ccomp c
     
     
    where ind.no_individu=aff.no_dossier_pers
    -- Structures et affectations
    and aff.c_structure=str.c_structure
    and aff.d_deb_affectation <= (select sysdate from dual)
    and (aff.d_fin_affectation >= (select sysdate from dual) or aff.d_fin_affectation is null)
    and aff.tem_valide='O' 
    -- Planning
    and aff.no_seq_affectation=pan.oid_affectation
     
    and ind.no_individu=c.numero(+)
    and ind.no_individu=h.numero(+) 
     
    group by ind.no_individu, ind.nom_affichage, ind.prenom_affichage, str.ll_structure, decode(h.dureeminute,'',0,h.dureeminute), decode(c.dureeminute,'',0,c.dureeminute), decode(h.dureeminute,'',0,h.dureeminute) + decode(c.dureeminute,'',0,c.dureeminute)
     
    order by Nom, Prénom, Service
    Le but n'est pas non plus d'y perdre trop de temps dessus.

  4. #4
    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
    Il y a un petit condensé de mauvais et/ou vieux code dans ces requêtes !
    Quelle est votre version d'Oracle ?

  5. #5
    Membre averti
    Homme Profil pro
    Administrateur de base de données
    Inscrit en
    Avril 2011
    Messages
    16
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 41
    Localisation : France, Cher (Centre)

    Informations professionnelles :
    Activité : Administrateur de base de données
    Secteur : Service public

    Informations forums :
    Inscription : Avril 2011
    Messages : 16
    Par défaut
    Citation Envoyé par Waldar Voir le message
    Il y a un petit condensé de mauvais et/ou vieux code dans ces requêtes !
    Quelle est votre version d'Oracle ?
    Ca vient de moi les mauvais et vieux codes

    La version : 10.2.0.4.0

  6. #6
    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
    Vraiment sans aucune arrière pensée, essayez de passer de temps en temps sur ce forum, même sur des sujets qui à priori ne vous intéressent pas : il regorge d'excellentes idées et de syntaxe moderne !

    Revenons à vos requêtes.
    J'ai procédé aux modifications suivantes :
    • Jointures ANSI (syntaxe normative, séparation des jointures et des filtres)
    • Fonction decode (propriétaire Oracle) -> case (multi sgbd, et beaucoup plus puissante) -- en fait la fonction a disparu dans le pivot
    • Formatage de la durée avec un code plus court (peut encore être raccourci si les durées sont toujours inférieures à 24h)
    • Suppression des sous-requêtes sur dual pour sysdate
    • Suppression des distincts inutiles (puisqu'il y a déjà un regroupement agrégé, les données seront déjà distinctes)
    • Ajout du pivot selon l'exemple que je vous ai proposé

    De ce que j'ai compris de votre code, les durées des congés compensateurs sont saisies en négatifs.
    Au final, ça devrait donner ceci (et ça remplace vos trois requêtes) :
    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
      SELECT ind.no_individu      AS numero
           , ind.nom_affichage    AS Nom
           , ind.prenom_affichage AS Prénom
           , str.ll_structure     AS Service
           , to_char(trunc(sum(case occ.type when 12 then      occ.duree else 0 end) / 60)) || 'h' || 
             to_char(  mod(sum(case occ.type when 12 then      occ.duree else 0 end) , 60), 'fm00') as HeureSupp
           , to_char(trunc(sum(case occ.type when 11 then -1 * occ.duree else 0 end) / 60)) || 'h' || 
             to_char(  mod(sum(case occ.type when 11 then -1 * occ.duree else 0 end) , 60), 'fm00') as CongesComp
           , to_char(trunc(sum(occ.duree) / 60)) || 'h' || 
             to_char(  mod(sum(occ.duree) , 60), 'fm00') as Solde
        FROM grhum.individu_ulr ind
             INNER JOIN mangue.affectation aff
               ON aff.no_dossier_pers = ind.no_individu
             INNER JOIN grhum.structure_ulr str
               ON str.c_structure = aff.c_structure
             INNER JOIN conges.plng_per_aff_ann pan
               ON pan.oid_affectation = aff.no_seq_affectation
             INNER JOIN conges.plng_aff_ann aan
               ON aan.oid = pan.oid_aff_ann
             INNER JOIN conges.plng_occ occ
               ON occ.oid_aff_ann = aan.oid
       WHERE aff.tem_valide = 'O'
        -- Affectations
         AND  aff.d_deb_affectation <= sysdate
         AND (aff.d_fin_affectation >= sysdate OR aff.d_fin_affectation is null)
        -- Etat validé
         AND occ.STATUS = 0
        -- Sur du planning réél
         AND occ.flg_nature = 'R'
         AND occ.type in (11, 12) 
    GROUP BY ind.no_individu     
           , ind.nom_affichage   
           , ind.prenom_affichage
           , str.ll_structure
    ORDER BY ind.nom_affichage    asc
           , ind.prenom_affichage asc
           , str.ll_structure     asc;

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

Discussions similaires

  1. Réponses: 10
    Dernier message: 04/03/2013, 10h28
  2. Plusieurs trigger sur une même table / Performances
    Par tchoimars dans le forum PL/SQL
    Réponses: 2
    Dernier message: 27/01/2010, 15h58
  3. Suivi de plusieurs plans d'actions sur une même table
    Par Mac_yavel dans le forum Modélisation
    Réponses: 2
    Dernier message: 20/07/2007, 13h44
  4. [MySQL] Plusieurs même requetes sur une même table
    Par bibom dans le forum PHP & Base de données
    Réponses: 14
    Dernier message: 27/07/2006, 12h54
  5. Sum différents sur sur une même table ...
    Par Saloucious dans le forum Langage SQL
    Réponses: 4
    Dernier message: 05/10/2005, 15h51

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