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 de requêtes imbriquées


Sujet :

Langage SQL

  1. #1
    Membre à l'essai
    Inscrit en
    Mai 2013
    Messages
    24
    Détails du profil
    Informations forums :
    Inscription : Mai 2013
    Messages : 24
    Points : 14
    Points
    14
    Par défaut Problème de requêtes imbriquées
    Bonjour,

    J'ai réalisé deux requêtes qui fonctionnent parfaitement: Nbre d'actions d'améliorations et Nbre d'actions préventives et je souhaiterai en réaliser une 3eme qui me permette d'afficher le ratio nbre d'action préventive / nbre d'actions d'améliorations. Pour cela j'ai utilisé la fonction UNION, mais la requête refuse de fonctionner:
    "Syntaxe incorrecte vers le mot clé 'GROUP'."
    si je supprime le dernier GROUP BY j'ai ce message: "Syntaxe incorrecte vers ')'."

    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
     
    SELECT (Nbre_actions_préventives / Nbre_actions_améliorations) as 'Pourcentage_actions_préventives', Month(T_Action_Amelioration.AMDateCreation) AS 'Mois', Year(T_Action_Amelioration.AMDateCreation) AS 'Année'
    FROM 
    (
    SELECT Count(T_Action_Amelioration.AMLngId) as 'Nbre_actions_améliorations', Month(T_Action_Amelioration.AMDateCreation) AS 'Mois', Year(T_Action_Amelioration.AMDateCreation) AS 'Année'
    FROM dbo.T_Action_Amelioration T_Action_Amelioration
    WHERE (Year(T_Action_Amelioration.AMDateCreation) >= '2012')
    GROUP BY Month(T_Action_Amelioration.AMDateCreation), Year(T_Action_Amelioration.AMDateCreation)
    UNION
     
    SELECT Count(T_Action_Amelioration.AMLngId) as 'Nbre_actions_préventives', Month(T_Action_Amelioration.AMDateCreation) AS 'Mois', Year(T_Action_Amelioration.AMDateCreation) AS 'Année'
    FROM dbo.T_Action_Amelioration T_Action_Amelioration
    WHERE (Year (T_Action_Amelioration.AMDateCreation) >='2012') AND (T_Action_Amelioration.AMLngTypeId=0)
    GROUP BY Month(T_Action_Amelioration.AMDateCreation), Year(T_Action_Amelioration.AMDateCreation)
    )
    GROUP BY Month(T_Action_Amelioration.AMDateCreation), Year(T_Action_Amelioration.AMDateCreation);
    Je suis sous SQLserver, merci d'avance

  2. #2
    Modérateur

    Profil pro
    dba
    Inscrit en
    Janvier 2010
    Messages
    5 643
    Détails du profil
    Informations personnelles :
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : dba

    Informations forums :
    Inscription : Janvier 2010
    Messages : 5 643
    Points : 13 092
    Points
    13 092
    Par défaut
    Bonjour

    Il faut simplement donner un alias à votre sous requete :

    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
     
    SELECT (Nbre_actions_préventives / Nbre_actions_améliorations) AS 'Pourcentage_actions_préventives', Month(T_Action_Amelioration.AMDateCreation) AS 'Mois', Year(T_Action_Amelioration.AMDateCreation) AS 'Année'
    FROM 
    (
    SELECT Count(T_Action_Amelioration.AMLngId) AS 'Nbre_actions_améliorations', Month(T_Action_Amelioration.AMDateCreation) AS 'Mois', Year(T_Action_Amelioration.AMDateCreation) AS 'Année'
    FROM dbo.T_Action_Amelioration T_Action_Amelioration
    WHERE (Year(T_Action_Amelioration.AMDateCreation) >= '2012')
    GROUP BY Month(T_Action_Amelioration.AMDateCreation), Year(T_Action_Amelioration.AMDateCreation)
    UNION
     
    SELECT Count(T_Action_Amelioration.AMLngId) AS 'Nbre_actions_préventives', Month(T_Action_Amelioration.AMDateCreation) AS 'Mois', Year(T_Action_Amelioration.AMDateCreation) AS 'Année'
    FROM dbo.T_Action_Amelioration T_Action_Amelioration
    WHERE (Year (T_Action_Amelioration.AMDateCreation) >='2012') AND (T_Action_Amelioration.AMLngTypeId=0)
    GROUP BY Month(T_Action_Amelioration.AMDateCreation), Year(T_Action_Amelioration.AMDateCreation)
    ) UnAlias
    GROUP BY Month(T_Action_Amelioration.AMDateCreation), Year(T_Action_Amelioration.AMDateCreation);
    Au passage, vous devriez remplacer les
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    WHERE (Year (T_Action_Amelioration.AMDateCreation) >='2012')
    par des
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    WHERE T_Action_Amelioration.AMDateCreation >='2012-01-01T00:00:00'
    Afin que le moteur puisse profiter d'un éventuel index sur cette colonne

  3. #3
    Membre à l'essai
    Inscrit en
    Mai 2013
    Messages
    24
    Détails du profil
    Informations forums :
    Inscription : Mai 2013
    Messages : 24
    Points : 14
    Points
    14
    Par défaut
    Merci pour votre réponse aieeeuuuuu mais cela ne fonctionne toujours pas:

    En ajoutant un alias à ma sous requête j'obtiens une nouvelle erreur:
    "L'identificateur en plusieurs parties "T_Action_Amelioration.AMDateCreation" ne peut pas être lié."

    Si je supprime des SELECT les champs: Month(T_Action_Amelioration.AMDateCreation) AS 'Mois', Year(T_Action_Amelioration.AMDateCreation) AS 'Année' ainsi que les GROUP BY j'obtiens cette erreur: Syntaxe incorrecte vers le mot clé 'FROM'.

    j'ai également essayé de charger la requête sous microsoft query, celui-ci quoi que je change dans ma requête m'affiche la même erreur: Impossible d'ajouter la table "(".

  4. #4
    Expert éminent sénior
    Homme Profil pro
    Responsable Données
    Inscrit en
    Janvier 2009
    Messages
    5 286
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 50
    Localisation : France, Hérault (Languedoc Roussillon)

    Informations professionnelles :
    Activité : Responsable Données

    Informations forums :
    Inscription : Janvier 2009
    Messages : 5 286
    Points : 12 991
    Points
    12 991
    Par défaut
    Bonjour,
    Si je ne m'abuse, la sous-requête ne renvoie que 3 colonnes: 'Nbre_actions_améliorations, mois et année.
    Donc le premier select ne peut porter que sur ces 3 colonne, mais ni sur 'Nbre_actions_préventives', ni sur T_Action_Amelioration.AMDateCreation.

    Pour le vérifier, il suffit de ne lancer que la requête interne.

    Tatayo.

  5. #5
    Membre à l'essai
    Inscrit en
    Mai 2013
    Messages
    24
    Détails du profil
    Informations forums :
    Inscription : Mai 2013
    Messages : 24
    Points : 14
    Points
    14
    Par défaut
    Bonjour Tatayo,
    La sous requête renvoie effectivement 3 colonnes, mais le premier SELECT affiche également 3 colonnes du même type et dans le même ordre.

  6. #6
    Modérateur

    Profil pro
    dba
    Inscrit en
    Janvier 2010
    Messages
    5 643
    Détails du profil
    Informations personnelles :
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : dba

    Informations forums :
    Inscription : Janvier 2010
    Messages : 5 643
    Points : 13 092
    Points
    13 092
    Par défaut
    non, dans le select de votre requete principale, vous avez
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    Year(T_Action_Amelioration.AMDateCreation)
    C'est ce T_Action_Amelioration.AMDateCreation qu'il ne trouve pas : à ce niveau, T_Action_Amelioration n'existe pas.

  7. #7
    Membre à l'essai
    Inscrit en
    Mai 2013
    Messages
    24
    Détails du profil
    Informations forums :
    Inscription : Mai 2013
    Messages : 24
    Points : 14
    Points
    14
    Par défaut
    D'accord je vois.
    Ma requete après modif:

    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
    SELECT (Nbre_actions_préventives / Nbre_actions_améliorations) as 'Pourcentage_action_préventives',Mois,Année
    FROM 
    (
    SELECT Count(T_Action_Amelioration.AMLngId) as 'Nbre_actions_améliorations', datename(m,T_Action_Amelioration.AMDateCreation) AS 'Mois', Year(T_Action_Amelioration.AMDateCreation) AS 'Année'
    FROM dbo.T_Action_Amelioration T_Action_Amelioration
    WHERE (Year(T_Action_Amelioration.AMDateCreation) >= '2012')
    GROUP BY datename(m,T_Action_Amelioration.AMDateCreation), Year(T_Action_Amelioration.AMDateCreation)
     
    UNION
     
    SELECT Count(T_Action_Amelioration.AMLngId) as 'Nbre_actions_préventives', datename(m,T_Action_Amelioration.AMDateCreation) AS 'Mois', Year(T_Action_Amelioration.AMDateCreation) AS 'Année'
    FROM dbo.T_Action_Amelioration T_Action_Amelioration
    WHERE (Year (T_Action_Amelioration.AMDateCreation) >='2012') AND (T_Action_Amelioration.AMLngTypeId=0)
    GROUP BY datename(m,T_Action_Amelioration.AMDateCreation), Year(T_Action_Amelioration.AMDateCreation)
    )
    GROUP BY Mois, Année;
    Le message d'erreur que j'obtiens après modification: Syntaxe incorrecte vers le mot clé 'GROUP'.

  8. #8
    Modérateur

    Profil pro
    dba
    Inscrit en
    Janvier 2010
    Messages
    5 643
    Détails du profil
    Informations personnelles :
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : dba

    Informations forums :
    Inscription : Janvier 2010
    Messages : 5 643
    Points : 13 092
    Points
    13 092
    Par défaut
    c'est normal, vous avez la même erreur dans le group by !
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    GROUP BY Month(T_Action_Amelioration.AMDateCreation), Year(T_Action_Amelioration.AMDateCreation);
    T_Action_Amelioration n'existe QUE dans votre sous requete

  9. #9
    Membre à l'essai
    Inscrit en
    Mai 2013
    Messages
    24
    Détails du profil
    Informations forums :
    Inscription : Mai 2013
    Messages : 24
    Points : 14
    Points
    14
    Par défaut
    Je ne comprends pas... Dans mon dernier GROUP BY je ne reprends pas T_Action_Amelioration pourtant, seulement dans la sous requete.

    J'ai supprimé les GROUP BY des sous requêtes pour plus de clarté (ils ne sont pas indispensables il me semble)


    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
    SELECT (Nbre_actions_préventives / Nbre_actions_améliorations) as 'Pourcentage_action_préventives',Mois,Année
    FROM 
    (
    SELECT Count(T_Action_Amelioration.AMLngId) as 'Nbre_actions_améliorations', datename(m,T_Action_Amelioration.AMDateCreation) AS 'Mois', Year(T_Action_Amelioration.AMDateCreation) AS 'Année'
    FROM dbo.T_Action_Amelioration T_Action_Amelioration
    WHERE (Year(T_Action_Amelioration.AMDateCreation) >= '2012')
     
    UNION 
     
    SELECT Count(T_Action_Amelioration.AMLngId) as 'Nbre_actions_préventives', datename(m,T_Action_Amelioration.AMDateCreation) AS 'Mois', Year(T_Action_Amelioration.AMDateCreation) AS 'Année'
    FROM dbo.T_Action_Amelioration T_Action_Amelioration
    WHERE (Year (T_Action_Amelioration.AMDateCreation) >='2012') AND (T_Action_Amelioration.AMLngTypeId=0)
     
    )
    GROUP BY Mois, Année;

  10. #10
    Expert éminent sénior
    Homme Profil pro
    Responsable Données
    Inscrit en
    Janvier 2009
    Messages
    5 286
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 50
    Localisation : France, Hérault (Languedoc Roussillon)

    Informations professionnelles :
    Activité : Responsable Données

    Informations forums :
    Inscription : Janvier 2009
    Messages : 5 286
    Points : 12 991
    Points
    12 991
    Par défaut
    Je maintiens ce que je dis: la sous-requête ne renvoie que 3 colonnes: Nbre_actions_améliorations,mois,annee.
    Donc le premier sélect ne connais pas Nbre_actions_préventives.

    Tatayo.

  11. #11
    Membre à l'essai
    Inscrit en
    Mai 2013
    Messages
    24
    Détails du profil
    Informations forums :
    Inscription : Mai 2013
    Messages : 24
    Points : 14
    Points
    14
    Par défaut
    Oui vous devez avoir raison tatayo, après avoir fait quelques modifications j'obtiens cette erreur: Nom de colonne non valide*: 'Nbre_actions_préventives'.

    Que proposeriez vous pour corriger ce problème ?

  12. #12
    Modérateur

    Profil pro
    dba
    Inscrit en
    Janvier 2010
    Messages
    5 643
    Détails du profil
    Informations personnelles :
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : dba

    Informations forums :
    Inscription : Janvier 2010
    Messages : 5 643
    Points : 13 092
    Points
    13 092
    Par défaut
    Citation Envoyé par Genap Voir le message
    Je ne comprends pas... Dans mon dernier GROUP BY je ne reprends pas T_Action_Amelioration pourtant, seulement dans la sous requete.

    En effet, j'avais mal lu !

    Tatayo en revenche, a parfaitement bien lu ! et pour détailler ce qu'il vous dit, lorsque vous faites :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    SELECT UneColonne AS UnAlias
    FROM UneTable
    UNION 
    SELECT UneColonne AS UnAUTREAlias
    FROM UneTable
    Vous aurez un résultat avec une seule colonne nommée UnAlias (contenant également les résultats de la deuxième requête : UnAUTREAlias n'est pas pris en compte.)

    Par ailleurs, vous faites un UNION et non pas un UNION ALL. Donc le résultat est dédoublonné, ce qui, a priori, n'est pas ce que vous voulez.

    Enfin, je pense que votre requête peut s’écrire tout simplement comme ceci :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
     
    SELECT 
    		SUM(CASE WHEN T_Action_Amelioration.AMLngTypeId=0 THEN 1 ELSE 0 END) 
    		/
    		COUNT(T_Action_Amelioration.AMLngId) AS 'Pourcentage_actions_préventives'
    	,	MONTH(T_Action_Amelioration.AMDateCreation) AS 'Mois'
    	,	YEAR(T_Action_Amelioration.AMDateCreation) AS 'Année'
    FROM		dbo.T_Action_Amelioration T_Action_Amelioration
    WHERE		T_Action_Amelioration.AMDateCreation) >= '2012-01-01T00:00:00'
    GROUP BY	MONTH(T_Action_Amelioration.AMDateCreation)
    		,	YEAR(T_Action_Amelioration.AMDateCreation)

  13. #13
    Membre à l'essai
    Inscrit en
    Mai 2013
    Messages
    24
    Détails du profil
    Informations forums :
    Inscription : Mai 2013
    Messages : 24
    Points : 14
    Points
    14
    Par défaut
    Oui je me doutais qu'il était possible de réaliser la requête sans passer par un UNION

    Mais je vais devoir faire beaucoup de requêtes répondant a une structure similaire (utilisation des résultats de 2 requêtes pour faire des stats). Si j'arrive à faire marcher cette requête (avec l'UNION ALL) cela me permettrait d'avoir une structure de départ identique ce qui me faciliterai beaucoup le travail pour la suite.

  14. #14
    Membre à l'essai
    Inscrit en
    Mai 2013
    Messages
    24
    Détails du profil
    Informations forums :
    Inscription : Mai 2013
    Messages : 24
    Points : 14
    Points
    14
    Par défaut
    J'ai fait appelle à des collègues ingé informaticiens, j'ai eu enfin m'a solution

    Si ça peut servir...:
    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 cast(cast(Nbre_actions_préventives as float) / cast(Nbre_actions_améliorations as float) AS decimal (10,3)) as 'Pourcentage_action_préventives', A.Mois, A.Année
    FROM 
    (
          SELECT Count(T_Action_Amelioration.AMLngId) as 'Nbre_actions_améliorations', datename(m,T_Action_Amelioration.AMDateCreation) AS 'Mois', Year(T_Action_Amelioration.AMDateCreation) AS 'Année'
          FROM dbo.T_Action_Amelioration T_Action_Amelioration
          WHERE (Year(T_Action_Amelioration.AMDateCreation) >= '2012')
          GROUP BY datename(m,T_Action_Amelioration.AMDateCreation), Year(T_Action_Amelioration.AMDateCreation)
    ) A
    join(
     
          SELECT Count(T_Action_Amelioration.AMLngId) as 'Nbre_actions_préventives', datename(m,T_Action_Amelioration.AMDateCreation) AS 'Mois', Year(T_Action_Amelioration.AMDateCreation) AS 'Année'
          FROM dbo.T_Action_Amelioration T_Action_Amelioration
          WHERE (Year (T_Action_Amelioration.AMDateCreation) >='2012') AND (T_Action_Amelioration.AMLngTypeId=0)
          GROUP BY datename(m,T_Action_Amelioration.AMDateCreation), Year(T_Action_Amelioration.AMDateCreation)
    ) B
          on A.Année=B.Année and A.Mois=B.Mois
    GROUP BY A.Mois, A.Année,Nbre_actions_améliorations, Nbre_actions_préventives;

  15. #15
    Expert éminent sénior
    Homme Profil pro
    Responsable Données
    Inscrit en
    Janvier 2009
    Messages
    5 286
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 50
    Localisation : France, Hérault (Languedoc Roussillon)

    Informations professionnelles :
    Activité : Responsable Données

    Informations forums :
    Inscription : Janvier 2009
    Messages : 5 286
    Points : 12 991
    Points
    12 991
    Par défaut
    J'ai du mal à voir l'intérêt du dernier GROUP BY, vu qu'il n'y a aucune fonction d'aggrégation dans le SELECT corrrespondant, et que toutes les colonnes du résultat sont dans le GROUP BY.
    De plus, comme les deux sous-requêtes regroupent les lignes de résultat par mois/année, et que la jointure entre A et B se fait sur ces même colonnes, il ne doit y avoir qu'une seule ligne de résultat par couple mois/année.
    A quoi bon faire un regroupement ?

    Tatayo.

  16. #16
    Modérateur

    Profil pro
    dba
    Inscrit en
    Janvier 2010
    Messages
    5 643
    Détails du profil
    Informations personnelles :
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : dba

    Informations forums :
    Inscription : Janvier 2010
    Messages : 5 643
    Points : 13 092
    Points
    13 092
    Par défaut
    on pourrait surtout obtenir le même résultat avec la requête que j'avais proposée, mais en évitant la jointure ce qui serait plus performant.

    J'avais par contre en effet omis le transtypage qui est nécessaire dans ce cas.

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

Discussions similaires

  1. Problème de requêtes imbriquées, possible sous Access ?
    Par PierrePM dans le forum Requêtes et SQL.
    Réponses: 17
    Dernier message: 14/11/2007, 20h45
  2. problème sur requête imbriqué
    Par Dam1en dans le forum Langage SQL
    Réponses: 2
    Dernier message: 21/10/2007, 17h55
  3. problème de requête imbriquées
    Par mehdiing dans le forum SQL
    Réponses: 11
    Dernier message: 30/07/2007, 09h51
  4. [MySQL] problème de requête imbriquée
    Par amarcil dans le forum PHP & Base de données
    Réponses: 8
    Dernier message: 28/04/2007, 16h04
  5. [MySQL] problème de requêtes imbriquées
    Par xave dans le forum PHP & Base de données
    Réponses: 3
    Dernier message: 24/01/2007, 14h30

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