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

Langage SQL Discussion :

[Problème SQL] Sum, Count + requête imbriquée


Sujet :

Langage SQL

  1. #1
    Membre confirmé
    Inscrit en
    Mai 2007
    Messages
    177
    Détails du profil
    Informations forums :
    Inscription : Mai 2007
    Messages : 177
    Par défaut [Problème SQL] Sum, Count + requête imbriquée
    Bonjour,

    Je tente d'accéder à un pourcentage.

    Pour expliquer dans les grandes lignes une business line est un ensemble de projets. Ces projets utilisent ou pas une information s'appelant SLA. J'arrive à accéder au nombre de projets par mois utilisant cette information.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
     
     
    SELECT distinct 
      T5.dbid, 
      T5.name as business_line,
      count(distinct T1.project_name) as Nb_projet_SLA, 
      to_char(T1.submit_date, 'yyyy-mm') as mois 
    FROM business_line T5 
    INNER JOIN incident T1 ON T1.business_line = T5.dbid 
    WHERE (T1.dbid <> 0 and (T1.sla_value > '0' or T1.intervention_delay > '0'))
    GROUP BY T5.dbid, T5.name, to_char(T1.submit_date, 'yyyy-mm') 
    ORDER BY to_char(T1.submit_date, 'yyyy-mm')
    Seulement maintenant je voudrais avoir un pourcentage au lieu du count(...).
    Mais pas un pourcentage de tous les projets !! Il me faudrait un pourcentage sur tous les projets de la business line !

    Du coup j'ai deux problèmes :
    1 - comment réaliser un pourcentage ?
    2 - comment faire la jointure sur la business line ?

    1 - J'avais pensé à réaliser un
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    sum((count(distinct T1.project_name)*100)/(count(...)))
    mais ça n'a pas l'air de fonctionner

    2 - Pour la jointure je dois faire un select imbriqué :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    sum((count(distinct T1.project_name)*100)/(select count(distinct T2.dbid) from Project T2, parent_child_links T3mm, Business_line T3 where T2.dbid = T3mm.child_dbid  (+) and 16778549 = T3mm.child_fielddef_id  (+) and T3mm.parent_dbid = T3.dbid  (+) group by T2.name))
    Le modérateur CinePhil m'a déjà expliqué qu'il était mieux de faire des jointures normalisées avec des INNER JOIN mais je fais du SQL propriétaire IBM. En saisissant la requête à la main en choisissant avec la souris les champs business_line et incident la jointure est réalisée de cette façon. Ne me demandez pas pourquoi ? Mais je ne peux pas les modifier sinon il ne reconnait plus grand chose. Mon problème n'est en réalité pas là mais est au niveau du nombre de projet DE LA BUSINESS_LINE ?? Je ne vois pas comment sélectionner les projets correspondant à la business_line sorties dans le select "au-dessus".

    C'est assez compliqué de m'expliquer, j'espère que vous pourrez au moins me donner des pistes.
    Merci par avance,

    Elodie

  2. #2
    Membre Expert Avatar de pacmann
    Homme Profil pro
    Consulté Oracle
    Inscrit en
    Juin 2004
    Messages
    1 626
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 44
    Localisation : France, Bas Rhin (Alsace)

    Informations professionnelles :
    Activité : Consulté Oracle
    Secteur : Distribution

    Informations forums :
    Inscription : Juin 2004
    Messages : 1 626
    Par défaut
    Salut !

    J'ai cru voir sur un autre post une erreur ORA...

    Quelle version d'ORACLE ?
    Après la V 8, tu peux éventuellement utiliser les fonctions analytiques

    PS : C'est cruel d'obliger les gens à utiliser des générateurs de SQL...

  3. #3
    Membre confirmé
    Profil pro
    Inscrit en
    Décembre 2006
    Messages
    69
    Détails du profil
    Informations personnelles :
    Localisation : Suisse

    Informations forums :
    Inscription : Décembre 2006
    Messages : 69
    Par défaut
    J'ai déjà une piste:

    Attention à l'usage de count, voici la syntaxe:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    SELECT COUNT(expression)
    FROM tables
    WHERE predicates;
    Je continu à chercher, mais je pense que ca devrait aller mieux...

  4. #4
    Membre Expert Avatar de pacmann
    Homme Profil pro
    Consulté Oracle
    Inscrit en
    Juin 2004
    Messages
    1 626
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 44
    Localisation : France, Bas Rhin (Alsace)

    Informations professionnelles :
    Activité : Consulté Oracle
    Secteur : Distribution

    Informations forums :
    Inscription : Juin 2004
    Messages : 1 626
    Par défaut
    Citation Envoyé par iks22 Voir le message
    J'ai déjà une piste:

    Attention à l'usage de count, voici la syntaxe:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    SELECT COUNT(expression)
    FROM tables
    WHERE predicates;
    Je continu à chercher, mais je pense que ca devrait aller mieux...
    Euh, c'est la syntaxe COUNT(DISTINCT expression) qui te dérange ?
    Parce que je t'assure, ça existe...

  5. #5
    Membre confirmé
    Profil pro
    Inscrit en
    Décembre 2006
    Messages
    69
    Détails du profil
    Informations personnelles :
    Localisation : Suisse

    Informations forums :
    Inscription : Décembre 2006
    Messages : 69
    Par défaut
    count (Distinct Expression) est toujours = 1, non? Puisque tu as le distinct...

  6. #6
    Membre Expert Avatar de pacmann
    Homme Profil pro
    Consulté Oracle
    Inscrit en
    Juin 2004
    Messages
    1 626
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 44
    Localisation : France, Bas Rhin (Alsace)

    Informations professionnelles :
    Activité : Consulté Oracle
    Secteur : Distribution

    Informations forums :
    Inscription : Juin 2004
    Messages : 1 626
    Par défaut
    Non.

    Tu comptes au sein de chaque groupe les valeurs distinctes d'une expression.
    Lorsque l'expression est constante, certes, ça vaut 1.
    COUNT(DISTINCT 'a') par exemple.

    Mais COUNT(DISTINCT projet) ... GROUP BY business_line, ça te compte le nombre de projets.

    Par exemple, si dans ta table incidents il y a :
    bl pj inc
    b1 p1 i1
    b1 p1 i2
    b1 p2 i3
    b2 p3 i4

    Le count distinct te renvoie : (b1, 2) et (b2, 1)
    Le count(*) ou count(1) ou count(n'importe quoi de constant) te renvoie : (b1, 3) et (b2, 1)

    On est d'accord ?

  7. #7
    Expert éminent
    Avatar de CinePhil
    Homme Profil pro
    Ingénieur d'études en informatique
    Inscrit en
    Août 2006
    Messages
    16 814
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 61
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Ingénieur d'études en informatique
    Secteur : Enseignement

    Informations forums :
    Inscription : Août 2006
    Messages : 16 814
    Billets dans le blog
    14
    Par défaut
    [quote=Lolie11;3910071]
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
     
     
    SELECT distinct 
      T5.dbid, 
      T5.name as business_line,
      count(distinct T1.project_name) as Nb_projet_SLA, 
      to_char(T1.submit_date, 'yyyy-mm') as mois 
    FROM business_line T5 
    INNER JOIN incident T1 ON T1.business_line = T5.dbid 
    WHERE (T1.dbid <> 0 and (T1.sla_value > '0' or T1.intervention_delay > '0'))
    GROUP BY T5.dbid, T5.name, to_char(T1.submit_date, 'yyyy-mm') 
    ORDER BY to_char(T1.submit_date, 'yyyy-mm')
    Comme il y a déjà
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    GROUP BY T5.dbid, T5.name, to_char(T1.submit_date, 'yyyy-mm')
    Pourquoi faire un SELECT DISTINCT ?

    Un truc bizarre aussi :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    INNER JOIN incident T1 ON T1.business_line = T5.dbid 
    WHERE (T1.dbid <> 0
    La jointure ne se ferait-elle pas plutôt sur T1.dbid ?

    Seulement maintenant je voudrais avoir un pourcentage au lieu du count(...).
    Mais pas un pourcentage de tous les projets !! Il me faudrait un pourcentage sur tous les projets de la business line !
    Procédons par ordre...

    1) Nombre de projets par mois et par business_line (apparemment, c'est ce que vous prenez comme regroupement) :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    SELECT T5.dbid, 
      T5.name AS business_line,
      count(distinct T1.project_name) AS Nb_projets_par_BL, 
      to_char(T1.submit_date, 'yyyy-mm') AS mois 
    FROM business_line T5 
    INNER JOIN incident T1 ON T1.business_line = T5.dbid 
    GROUP BY T5.dbid, T5.name, to_char(T1.submit_date, 'yyyy-mm') 
    ORDER BY to_char(T1.submit_date, 'yyyy-mm')
    En gros, c'est votre requête sans le WHERE. A noter que ceci devrait pouvoir fonctionner aussi :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    GROUP BY T5.dbid, T5.name, mois 
     ORDER BY mois
    Sauf que tous les projets ne figurent peut-être pas dans la table 'incident' ?
    N'y a t-il pas une table 'projets' avec une clé étrangère contenant le numéro de la business line ?

    Ce qui donnerait un truc du genre :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    SELECT dbid, COUNT(*) AS Nb_Projets_par_BL
    FROM projets
    GROUP BY dbid
    Plus simple non ?

    2) Le nombre de projets par business line ayant des SLA_value ou des intervention_delay supérieures à 0 (c'est ce que sélectionne votre WHERE non ?).
    Ben ça en gros c'est votre requête complète il me semble !

    3) On réunit les deux et on calcule le pourcentage :
    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
    SELECT
      T5.dbid, 
      T5.name as business_line,
      count(distinct T1.project_name) as Nb_projet_SLA, 
      (100 * count(distinct T1.project_name)) / T6.Nb_Projets_par_BL AS PCent_Projets_SLA,
      to_char(T1.submit_date, 'yyyy-mm') as mois 
    FROM business_line T5 
    INNER JOIN incident T1 ON T1.business_line = T5.dbid 
    INNER JOIN (
      SELECT dbid, COUNT(*) AS Nb_Projets_par_BL
       FROM projets
       GROUP BY dbid
    ) T6 ON T5.dbid = T6.dbid
    WHERE (T1.dbid <> 0 and (T1.sla_value > '0' or T1.intervention_delay > '0'))
    GROUP BY T5.dbid, T5.name, mois
    ORDER BY mois
    A adapter et à essayer. J'ai remis en gras les trucs qui me semblaient bizarres.
    Philippe Leménager. Ingénieur d'étude à l'École Nationale Supérieure de Formation de l'Enseignement Agricole, en retraite... mais toujours Autoentrepreneur à l'occasion.
    Mon ancien blog sur la conception des BDD, le langage SQL, le PHP... et mon nouveau blog sur les mêmes sujets.
    « Ce que l'on conçoit bien s'énonce clairement, et les mots pour le dire arrivent aisément ». (Nicolas Boileau)
    À la maison comme au bureau, j'utilise la suite Linux Mageïa !

  8. #8
    Membre confirmé
    Inscrit en
    Mai 2007
    Messages
    177
    Détails du profil
    Informations forums :
    Inscription : Mai 2007
    Messages : 177
    Par défaut
    Youhou !! Ca fonctionne.

    Merci vraiment beaucoup. Je vous donne ma requête finale si ça peut aider d'autres personnes... même si c'est pas évident sans schéma mais bon au moins piger le mécanisme.

    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
     
     
    select distinct 
      T5.dbid, 
      T5.name as business_line,  
     
      (100 * count(distinct T1.project_name)) / T6.NbProj as Pcent_Projets,
     
      to_char(T1.submit_date, 'yyyy-mm') as mois 
    from business_line T5 
    inner join incident T1 on T1.business_line = T5.dbid  
     
    inner join (select T3.dbid, count(T2.name) as NbProj from project T2, business_line T3, parent_child_links T3mm  where T2.dbid <> 0 and T2.dbid = T3mm.child_dbid  (+) and 16778549 = T3mm.child_fielddef_id  (+) and T3mm.parent_dbid = T3.dbid  (+) group by T3.dbid) T6 on T5.dbid = T6.dbid
     
    where (T1.dbid <> 0 and ((T1.sla_value > '0' or T1.intervention_delay > '0')))
    group by T5.dbid, T5.name, to_char(T1.submit_date, 'yyyy-mm'), T6.NbProj 
    order by to_char(T1.submit_date, 'yyyy-mm')
    Merci beaucoup CinePhil, enfait je vois maintenant comment faire pour lier un select imbriqué à son select "imbriquant" !! Je vais essayer ça demain sur mes autres requêtes.

    Pour info mon code est tiré de l'outil ClearQuest. Cet outil IBM propose de développer des requêtes à la souris, c'est grâce à ça que j'ai pu voir les jointure bizarre avec le "16778549 = T..", je ne sais pas comment c'est généré. De même si on ne met pas le dbid <> 0 ça génère une erreur de compilation. De même lorsqu'à la souris on affiche les incidents d'une business_line, la jointure est faite sur le dbid de la business_line.

    Encore merci beaucoup !

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

Discussions similaires

  1. Problème requête SQL (HAVING COUNT / MAX)
    Par AuroreMu dans le forum Langage SQL
    Réponses: 2
    Dernier message: 28/11/2014, 17h24
  2. Réponses: 1
    Dernier message: 09/07/2013, 16h56
  3. [Toutes versions] Problème de syntaxe dans requêtes imbriquées
    Par BornToBe dans le forum Requêtes et SQL.
    Réponses: 4
    Dernier message: 25/04/2012, 17h31
  4. Problème de SUM sur une requête SQL
    Par Lapicure dans le forum Requêtes et SQL.
    Réponses: 1
    Dernier message: 12/06/2007, 11h51
  5. problème avec une requête imbriquée
    Par jaimepasteevy dans le forum Langage SQL
    Réponses: 13
    Dernier message: 05/12/2003, 10h29

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