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 :

Un Group By sans agrégation


Sujet :

Langage SQL

  1. #1
    Membre confirmé Avatar de juvamine
    Profil pro
    Chef de projet MOA
    Inscrit en
    Mai 2004
    Messages
    414
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations professionnelles :
    Activité : Chef de projet MOA
    Secteur : Agroalimentaire - Agriculture

    Informations forums :
    Inscription : Mai 2004
    Messages : 414
    Points : 502
    Points
    502
    Par défaut Un Group By sans agrégation
    Bonjour,

    je mets ça dans la section sql, mais c'est peut etre pas la plus appropriée.
    Je suis en train de migrer une database access vers ms sql-server.
    Je ne m'occupe que de la migration, je ne suis pas censé "redévelopper", c'est pour cela que dans un premier temps je ne dois pas décortiquer le code du module.
    Et je n'ai malheureusement plus possibilité de contacter le developpeur

    je reprends donc les requètes une à une, et je suis tombé sur un cas "bizarre" syntaxiquement parlant
    La voilà telle qu'elle est sous access:
    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
    SELECT SECTION_ANALYTIQUE.CodeSection, 
           SECTION_ANALYTIQUE.LibelleSection, 
           FACTURE_RELEVE.NumFacture AS NoFactAvoir, 
           IIf(IsNull([MtFactReleve]),[MtTotal],[MtFactReleve]) AS Mt, 
           'Facture' AS Type, 
           '' AS LettreDef
    FROM (DEMANDE_INTERIMAIRE INNER JOIN (RELEVE_HEURES INNER JOIN FACTURE_RELEVE ON 
            RELEVE_HEURES.NumReleve = FACTURE_RELEVE.NumReleve) ON 
            DEMANDE_INTERIMAIRE.NumDemandeInterim = RELEVE_HEURES.NumDemandeInterim) INNER JOIN SECTION_ANALYTIQUE ON 
            DEMANDE_INTERIMAIRE.CodeSection = SECTION_ANALYTIQUE.CodeSection
    GROUP BY SECTION_ANALYTIQUE.CodeSection, 
             SECTION_ANALYTIQUE.LibelleSection, 
             FACTURE_RELEVE.NumFacture, 
             IIf(IsNull([MtFactReleve]),[MtTotal],[MtFactReleve]), 
             'Facture', 
             '', 
             DEMANDE_INTERIMAIRE.NumDemandeInterim, 
             Format(RELEVE_HEURES.DateReleve-1,'ww'), 
             Month(RELEVE_HEURES!DateReleve), 
             Year(RELEVE_HEURES!DateReleve);
    Nous sommes en présence d'un group by et il n'y a pourtant aucune fonction d'agrégation plus haut...

    Sans trop comprendre au début j'ai voulu la transcrire telle qu'elle en SQL-SERVER:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    SELECT     dbo.SECTION_ANALYTIQUE.CodeSection, dbo.SECTION_ANALYTIQUE.LibelleSection, dbo.FACTURE_RELEVE.NumFacture AS NoFactAvoir, 
                          CASE WHEN MtFactReleve IS NULL THEN MtTotal ELSE MtFactReleve END AS Mt, 'Facture' AS Type, '' AS LettreDef
    FROM         dbo.DEMANDE_INTERIMAIRE INNER JOIN
                          dbo.RELEVE_HEURES INNER JOIN
                          dbo.FACTURE_RELEVE ON dbo.RELEVE_HEURES.NumReleve = dbo.FACTURE_RELEVE.NumReleve ON 
                          dbo.DEMANDE_INTERIMAIRE.NumDemandeInterim = dbo.RELEVE_HEURES.NumDemandeInterim INNER JOIN
                          dbo.SECTION_ANALYTIQUE ON dbo.DEMANDE_INTERIMAIRE.CodeSection = dbo.SECTION_ANALYTIQUE.CodeSection
    GROUP BY dbo.SECTION_ANALYTIQUE.CodeSection, dbo.SECTION_ANALYTIQUE.LibelleSection, dbo.FACTURE_RELEVE.NumFacture, 
                          CASE WHEN MtFactReleve IS NULL THEN MtTotal ELSE MtFactReleve END, 'Facture', '', dbo.DEMANDE_INTERIMAIRE.NumDemandeInterim, 
                          dbo.F_ISO_WEEK(dbo.RELEVE_HEURES.DateReleve - 1), MONTH(dbo.RELEVE_HEURES.DateReleve), YEAR(dbo.RELEVE_HEURES.DateReleve)
    (ou f_iso_week est une udf pour calculer le n° de la semaine)

    J'ai le message suivant:

    Chaque expression GROUP BY doit contenir au moins une colonne qui n'est pas une référence externe.
    je ne le trouve pas forcément explicite !

    j'ai essayé plusieurs possibilités, mettre toutes les colonnes du group by dans le select, etc, mais rien n'y fait. Message identique.

    Si j'enleve le group by je passe de 4000 records à 18000
    Si j'enlève le group by et que je met un distinct dans le select, je passe de 4000 records à 6000

    je n'arrive pas a trouver à quoi me sert ce group by, afin de le reproduire sous sql server

    vous avez une explication peut etre ??

    Merci d'avance !

  2. #2
    Membre éprouvé Avatar de Mathusalem
    Profil pro
    IT moa
    Inscrit en
    Décembre 2003
    Messages
    1 008
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations professionnelles :
    Activité : IT moa

    Informations forums :
    Inscription : Décembre 2003
    Messages : 1 008
    Points : 1 067
    Points
    1 067
    Par défaut
    Je suis perplexe, en plus de voir des constantes dans le group by, d'y voir bien plus de champs que dans le select.
    ça ressemble à une requête modifiée à l'arrache, dans lequel il a enlevé des champs du select qui ne lui servaient plus à rien.

    Ensuite, si il n'y a pas d'agrégation, ne devrais-tu pas, avec ou sans group by, trouver le même nombre de tuples en sortie ?
    Au lieu de faire un essai avec un distinct, essaye plutôt

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    select *, count(*)
    from...
    where...
    group by...
    having count(*) > 1
    et regarde bien ce qui doublonné. Je suppose qu'avec tous les champs du group by dans le select, il n'y a plus de doublons.

  3. #3
    Expert éminent
    Homme Profil pro
    Big Data / Freelance EURL
    Inscrit en
    Mars 2003
    Messages
    2 124
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 54
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Big Data / Freelance EURL

    Informations forums :
    Inscription : Mars 2003
    Messages : 2 124
    Points : 7 291
    Points
    7 291
    Par défaut
    heu ça ne serait pas cela qui est voulu ? :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    SELECT     dbo.SECTION_ANALYTIQUE.CodeSection, dbo.SECTION_ANALYTIQUE.LibelleSection, dbo.FACTURE_RELEVE.NumFacture AS NoFactAvoir, 
                          SUM(CASE WHEN MtFactReleve IS NULL THEN MtTotal ELSE MtFactReleve END) AS Mt, 'Facture' AS Type, '' AS LettreDef
    FROM         dbo.DEMANDE_INTERIMAIRE INNER JOIN
                          dbo.RELEVE_HEURES INNER JOIN
                          dbo.FACTURE_RELEVE ON dbo.RELEVE_HEURES.NumReleve = dbo.FACTURE_RELEVE.NumReleve ON 
                          dbo.DEMANDE_INTERIMAIRE.NumDemandeInterim = dbo.RELEVE_HEURES.NumDemandeInterim INNER JOIN
                          dbo.SECTION_ANALYTIQUE ON dbo.DEMANDE_INTERIMAIRE.CodeSection = dbo.SECTION_ANALYTIQUE.CodeSection
    GROUP BY dbo.SECTION_ANALYTIQUE.CodeSection, dbo.SECTION_ANALYTIQUE.LibelleSection, dbo.FACTURE_RELEVE.NumFacture, 
                           'Facture', '', dbo.DEMANDE_INTERIMAIRE.NumDemandeInterim, 
                          dbo.F_ISO_WEEK(dbo.RELEVE_HEURES.DateReleve - 1), MONTH(dbo.RELEVE_HEURES.DateReleve), YEAR(dbo.RELEVE_HEURES.DateReleve)

  4. #4
    Membre confirmé Avatar de juvamine
    Profil pro
    Chef de projet MOA
    Inscrit en
    Mai 2004
    Messages
    414
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations professionnelles :
    Activité : Chef de projet MOA
    Secteur : Agroalimentaire - Agriculture

    Informations forums :
    Inscription : Mai 2004
    Messages : 414
    Points : 502
    Points
    502
    Par défaut
    Citation Envoyé par phili_b Voir le message
    heu ça ne serait pas cela qui est voulu ? :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    SELECT     dbo.SECTION_ANALYTIQUE.CodeSection, dbo.SECTION_ANALYTIQUE.LibelleSection, dbo.FACTURE_RELEVE.NumFacture AS NoFactAvoir, 
                          SUM(CASE WHEN MtFactReleve IS NULL THEN MtTotal ELSE MtFactReleve END) AS Mt, 'Facture' AS Type, '' AS LettreDef
    FROM         dbo.DEMANDE_INTERIMAIRE INNER JOIN
                          dbo.RELEVE_HEURES INNER JOIN
                          dbo.FACTURE_RELEVE ON dbo.RELEVE_HEURES.NumReleve = dbo.FACTURE_RELEVE.NumReleve ON 
                          dbo.DEMANDE_INTERIMAIRE.NumDemandeInterim = dbo.RELEVE_HEURES.NumDemandeInterim INNER JOIN
                          dbo.SECTION_ANALYTIQUE ON dbo.DEMANDE_INTERIMAIRE.CodeSection = dbo.SECTION_ANALYTIQUE.CodeSection
    GROUP BY dbo.SECTION_ANALYTIQUE.CodeSection, dbo.SECTION_ANALYTIQUE.LibelleSection, dbo.FACTURE_RELEVE.NumFacture, 
                           'Facture', '', dbo.DEMANDE_INTERIMAIRE.NumDemandeInterim, 
                          dbo.F_ISO_WEEK(dbo.RELEVE_HEURES.DateReleve - 1), MONTH(dbo.RELEVE_HEURES.DateReleve), YEAR(dbo.RELEVE_HEURES.DateReleve)
    non bien sur...je dois retranscrire la 1ère requête que j'ai posté. C'est bien là mon problème: Quelle est l'utilité du group by sans agrégation ?

    Mathusalem je vais tester ta solution mais elle n'est pas si simple à mettre en oeuvre. J'y travail !

  5. #5
    Modérateur
    Avatar de al1_24
    Homme Profil pro
    Retraité
    Inscrit en
    Mai 2002
    Messages
    9 103
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 63
    Localisation : France, Val de Marne (Île de France)

    Informations professionnelles :
    Activité : Retraité
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Mai 2002
    Messages : 9 103
    Points : 28 394
    Points
    28 394
    Par défaut
    Un GROUP BY sans fonction d'agrégation qui reprend toutes les colonnes du SELECT fonctionne omme un SELECT DISTINCT.
    Toutefois, suivant les SGBD, cette première syntaxe se trouve être plus performante que la seconde.

Discussions similaires

  1. Que retourne un GROUP BY sans fonction d'agrégation?
    Par Maniz dans le forum Requêtes
    Réponses: 4
    Dernier message: 27/06/2012, 11h05
  2. [AC-2003] double pivot sans agrégat.
    Par mioux dans le forum Requêtes et SQL.
    Réponses: 1
    Dernier message: 10/11/2011, 09h33
  3. Group By et agrégats
    Par zouzoukha dans le forum Langage SQL
    Réponses: 3
    Dernier message: 21/03/2011, 14h45
  4. Réponses: 3
    Dernier message: 11/03/2009, 14h47
  5. comment faire un group by sans erreur
    Par phpaide dans le forum Langage SQL
    Réponses: 7
    Dernier message: 21/04/2006, 09h11

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