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

MS SQL Server Discussion :

Recherche solution élégante pour requête avec double agrégat


Sujet :

MS SQL Server

  1. #1
    FMJ
    FMJ est déconnecté
    Membre averti
    Profil pro
    tutu
    Inscrit en
    Octobre 2003
    Messages
    416
    Détails du profil
    Informations personnelles :
    Localisation : France, Aveyron (Midi Pyrénées)

    Informations professionnelles :
    Activité : tutu

    Informations forums :
    Inscription : Octobre 2003
    Messages : 416
    Points : 363
    Points
    363
    Par défaut Recherche solution élégante pour requête avec double agrégat
    Salut,

    Je pense que ma question doit être triviale et qu'il existe une façon élégante de la résoudre en une seule requête mais mes recherches perso + celles sur la doc, les FAQ et le forum ne m'ont pour l'instant pas permis d'y arriver.

    Je présente le problème : soit 2 tables T1 et T2
    Table T1 :
    Champ1 (a1)......./........ Champ2 (a2)
    A ......./........ 1
    A ......./........ 2
    B ......./........ 3
    B ......./........ 4

    Table T2 :
    Champ1 (b1) ......./........ Champ2 (b2)
    A ......./........ 10
    A ......./........ 20
    A ......./........ 30
    B ......./........ 40
    B ......./........ 50
    B ......./........ 60

    Les tables T1 et T2 sont liées par leur 1er champ (a1 = b1)

    si l'on fait l'agrégation séparée de ces 2 tables; cela donne :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    SELECT a1, sum(a2) as résultat1 FROM T1 GROUP BY a1
    Résultat :
    a1 ......./........ résultat1
    A ........../........ 2
    B ........../........ 7

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    SELECT b1, sum(b2) as résultat2 FROM T2 GROUP BY b1
    Résultat :
    b1 ........../........ résultat2
    A ........../........ 60
    B ........../........ 150


    Je cherche simplement à combiner ces deux résultats en une seule requête afin d'obtenir :

    Résultat :
    a1 ........../........ résultat1 ........../........ résultat2
    A ........../..................3 ................/........ 60
    B ........../..................7 ................/........ 150


    J'ai commencé par une simple jointure du type

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    SELECT a1, sum(a2) as résultat1, sum(b2) as résultat2 FROM T1 
    LEFT JOIN T2 ON a1=b1 GROUP BY a1
    qui donne pour résultat :
    a1 ........../........ résultat1 ........../........ résultat2
    A ........../.............. 3 ........../.............. 120
    B ........../.............. 7 ........../.............. 300

    On voit bien que l'une des agrégations est multipliée par le nombre d'occurrence de chaque enregistrement avant l'autre agrégation.


    J'ai donc ensuite essayé de passer par des sous-requêtes mais je bute

    > soit sur le non support des fonctions d'agrégation au niveau de la clause "ORDER BY" (MSG144: "Impossible de faire appel à un agrégat ou à une sous-requête dans une expression utilisée dans la liste GROUP BY d'une clause GROUP BY")
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    SELECT a1, sum(a2) as résultat1, 
    (SELECT sum(b2) as résultat2 FROM T2 WHERE b1=a1) 
    FROM T1 GROUP BY a1, (SELECT sum(b2) as résultat2 FROM T2 WHERE b1=a1)
    > soit sur un problème de non support d'une agrégation sur une sous-requête
    MSg130 : "Impossible d'exécuter une fonction d'agrégation sur une expression comportant un agrégat ou une sous-requête."
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    SELECT a1, sum(a2) as résultat1, 
    MAX(SELECT sum(b2) as résultat2 FROM T2 WHERE b1=a1)  
    FROM T1 GROUP BY a1

    J'ai ensuite une l'idée saugrenue de passer par la clause FROM et par une jointure, là aussi avec une erreur (MSG156 : "Syntaxe incorrecte vers le mot clé 'left'") :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    SELECT a1, SUM(a2) as résultat1, MAX(temp2) as résultat2 
    FROM (SELECT b1 as temp1, SUM(b2) as temp2 FROM T2) 
    LEFT JOIN T1 ON temp1=a1
    GROUP BY a1


    Alors bien sûr, ce résultat s'obtient très facilement en faisant une requête de requête mais j'aurais bien aimé savoir le faire en une seule requête.

    Merci d'avance de votre aide.

  2. #2
    Modérateur

    Homme Profil pro
    Administrateur de base de données
    Inscrit en
    Janvier 2005
    Messages
    5 826
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Administrateur de base de données
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Janvier 2005
    Messages : 5 826
    Points : 12 371
    Points
    12 371
    Par défaut
    Bonjour,

    Si vous êtes sous SQL Server 2005, vous avez la possibilité d'écrire cette requête à l'aide de CTEs (attention j'ai écrit JOIN, remplacez le par une demi-jointure si besoin est):

    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
    WITH 
    	CTE_T1 AS
    	(
    		SELECT a1, SUM(a2) SumA2
    		FROM T1
    		GROUP BY a1
    	),
    	CTE_T2 AS
    	(
    		SELECT b1, SUM(b2) SumB2
    		FROM T2
    		GROUP BY b1
    	)
    SELECT CTE_T1.a1, CTE_T1.SumA2, CTE_T2.SumB2
    FROM CTE_T1
    JOIN CTE_T2 ON CTE_T1.a1 = CTE_T2.b1
    Dans tous les cas, vous pouvez aussi écrire (même remarque qu'avec les CTEs):

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    SELECT SUB_T1.a1, SumA2, SumB2
    FROM (
    		SELECT a1, SUM(a2) SumA2
    		FROM T1
    		GROUP BY a1
    	) SUB_T1
    JOIN (
    		SELECT b1, SUM(b2) SumB2
    		FROM T2
    		GROUP BY b1
    	) SUB_T2 ON SUB_T1.a1 = SUB_T2.b1
    A+

  3. #3
    FMJ
    FMJ est déconnecté
    Membre averti
    Profil pro
    tutu
    Inscrit en
    Octobre 2003
    Messages
    416
    Détails du profil
    Informations personnelles :
    Localisation : France, Aveyron (Midi Pyrénées)

    Informations professionnelles :
    Activité : tutu

    Informations forums :
    Inscription : Octobre 2003
    Messages : 416
    Points : 363
    Points
    363
    Par défaut
    Salut,

    En fait, j'ai récemment vu cette possibilité suite à une solution proposée par SQLPRO sur un post.

    Malheureusement, je suis en SQL2000 et je ne peux utiliser cette facilité. C'est vrai que c'est énervant car ces CTE sont vraiment puissants

    Ca m'épate tout de même, je dois être nul. Ca paraît étonnant qu'il n'existe pas une solution simple d'implémenter ce requêtage qui paraît trivial sans sortir du standard SQL ????!!!!

    Merci quand même pour ta réponse.

  4. #4
    Rédacteur

    Avatar de SQLpro
    Homme Profil pro
    Expert bases de données / SQL / MS SQL Server / Postgresql
    Inscrit en
    Mai 2002
    Messages
    21 865
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Var (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Expert bases de données / SQL / MS SQL Server / Postgresql
    Secteur : Conseil

    Informations forums :
    Inscription : Mai 2002
    Messages : 21 865
    Points : 53 021
    Points
    53 021
    Billets dans le blog
    6
    Par défaut
    Passez par des vues...

    A +

  5. #5
    Modérateur

    Homme Profil pro
    Administrateur de base de données
    Inscrit en
    Janvier 2005
    Messages
    5 826
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Administrateur de base de données
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Janvier 2005
    Messages : 5 826
    Points : 12 371
    Points
    12 371
    Par défaut
    Bonsoir,

    La seconde requête n'est pas supportée par SQL Server 2000 ?

  6. #6
    FMJ
    FMJ est déconnecté
    Membre averti
    Profil pro
    tutu
    Inscrit en
    Octobre 2003
    Messages
    416
    Détails du profil
    Informations personnelles :
    Localisation : France, Aveyron (Midi Pyrénées)

    Informations professionnelles :
    Activité : tutu

    Informations forums :
    Inscription : Octobre 2003
    Messages : 416
    Points : 363
    Points
    363
    Par défaut
    Citation Envoyé par SQLpro Voir le message
    Passez par des vues...

    A +
    Merci de la réponse. Je vais donc me résigner.

    Notez que c'est tout de même rageant car dans l'absolu, le cadre de cette requête ne sort pas de la logique "une information --- une ligne".

  7. #7
    FMJ
    FMJ est déconnecté
    Membre averti
    Profil pro
    tutu
    Inscrit en
    Octobre 2003
    Messages
    416
    Détails du profil
    Informations personnelles :
    Localisation : France, Aveyron (Midi Pyrénées)

    Informations professionnelles :
    Activité : tutu

    Informations forums :
    Inscription : Octobre 2003
    Messages : 416
    Points : 363
    Points
    363
    Par défaut
    Citation Envoyé par elsuket Voir le message
    Bonsoir,

    La seconde requête n'est pas supportée par SQL Server 2000 ?
    Vous faites référence à celle-ci ?

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    SELECT a1, sum(a2) AS résultat1, 
    MAX(SELECT sum(b2) AS résultat2 FROM T2 WHERE b1=a1)  
    FROM T1 GROUP BY a1

    Dans l'affirmative, non, SQL2000 ne le supporte pas ! Cela génère le message d'erreur indiqué.

  8. #8
    Modérateur

    Homme Profil pro
    Administrateur de base de données
    Inscrit en
    Janvier 2005
    Messages
    5 826
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Administrateur de base de données
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Janvier 2005
    Messages : 5 826
    Points : 12 371
    Points
    12 371
    Par défaut
    Bonjour,

    Non, je voulais parler ce celle-ci:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    SELECT SUB_T1.a1, SumA2, SumB2
    FROM (
    		SELECT a1, SUM(a2) SumA2
    		FROM T1
    		GROUP BY a1
    	) SUB_T1
    JOIN (
    		SELECT b1, SUM(b2) SumB2
    		FROM T2
    		GROUP BY b1
    	) SUB_T2 ON SUB_T1.a1 = SUB_T2.b1

  9. #9
    FMJ
    FMJ est déconnecté
    Membre averti
    Profil pro
    tutu
    Inscrit en
    Octobre 2003
    Messages
    416
    Détails du profil
    Informations personnelles :
    Localisation : France, Aveyron (Midi Pyrénées)

    Informations professionnelles :
    Activité : tutu

    Informations forums :
    Inscription : Octobre 2003
    Messages : 416
    Points : 363
    Points
    363
    Par défaut
    Tu n'arrives pas au résultat attendu :
    1. Tu as 2 lignes de résultats par enregistrement
    2. Tu n'as qu'une colonne de résultat

    Par contre, il faut que j'essaye :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
     
    SELECT  val0, sum(val1), sum(val2) from
    (
    (SELECT T1.A1 AS val0, Sum(T1.A2) AS val1, 0 val2
    FROM T1
    GROUP BY T1.A1) 
    UNION
    (SELECT T2.B1 val0, 0 as val1, Sum(T2.B2) val2
    FROM T2
    GROUP BY T2.B1)
    )
    GROUP BY val0

  10. #10
    FMJ
    FMJ est déconnecté
    Membre averti
    Profil pro
    tutu
    Inscrit en
    Octobre 2003
    Messages
    416
    Détails du profil
    Informations personnelles :
    Localisation : France, Aveyron (Midi Pyrénées)

    Informations professionnelles :
    Activité : tutu

    Informations forums :
    Inscription : Octobre 2003
    Messages : 416
    Points : 363
    Points
    363
    Par défaut
    Salut !

    Non, j'ai testé cette dernière requête : SQL Server ne l'accepte pas (problème de syntaxe avec une parenthèse)

    J'ai pas d'autre solution dans la besace. Va falloir abdiquer

  11. #11
    Rédacteur

    Avatar de SQLpro
    Homme Profil pro
    Expert bases de données / SQL / MS SQL Server / Postgresql
    Inscrit en
    Mai 2002
    Messages
    21 865
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Var (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Expert bases de données / SQL / MS SQL Server / Postgresql
    Secteur : Conseil

    Informations forums :
    Inscription : Mai 2002
    Messages : 21 865
    Points : 53 021
    Points
    53 021
    Billets dans le blog
    6
    Par défaut
    Vous devez nommer les tables dérivées, et les requêtes union intersect et except ne demande en aucune manière des parenthèses !

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    SELECT  val0, sum(val1), sum(val2) FROM
    (
    SELECT T1.A1 AS val0, Sum(T1.A2) AS val1, 0 val2
    FROM T1
    GROUP BY T1.A1
    UNION
    SELECT T2.B1 val0, 0 AS val1, Sum(T2.B2) val2
    FROM T2
    GROUP BY T2.B1
    ) AS T3
    GROUP BY val0
    A +

  12. #12
    FMJ
    FMJ est déconnecté
    Membre averti
    Profil pro
    tutu
    Inscrit en
    Octobre 2003
    Messages
    416
    Détails du profil
    Informations personnelles :
    Localisation : France, Aveyron (Midi Pyrénées)

    Informations professionnelles :
    Activité : tutu

    Informations forums :
    Inscription : Octobre 2003
    Messages : 416
    Points : 363
    Points
    363
    Par défaut
    Eh CA MARCHE !!!!!!!!

    Une requête UNION était donc la solution (et faut bien penser à la nommer)

    Ce qui prouve que je suis décidément un gros nul en requêtage.


    Merci à elsuket pour l'idée et à M. SQLpro pour la correction

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

Discussions similaires

  1. Réponses: 3
    Dernier message: 29/11/2013, 18h11
  2. Réponses: 1
    Dernier message: 08/02/2006, 17h17
  3. Recherche de SRAM pour utilisation avec Dspic30C
    Par PoOky dans le forum Composants
    Réponses: 2
    Dernier message: 21/11/2005, 16h19
  4. Problème de requête avec l'agrégat
    Par bertrand_declerck dans le forum Langage SQL
    Réponses: 10
    Dernier message: 24/08/2005, 16h59

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