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 :

GROUP BY correct ou pas ? [Débutant(e)]


Sujet :

Langage SQL

  1. #1
    Expert éminent sénior
    Avatar de Domi2
    Homme Profil pro
    Gestionnaire
    Inscrit en
    Juin 2006
    Messages
    7 194
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 64
    Localisation : Suisse

    Informations professionnelles :
    Activité : Gestionnaire
    Secteur : Administration - Collectivité locale

    Informations forums :
    Inscription : Juin 2006
    Messages : 7 194
    Points : 16 044
    Points
    16 044
    Par défaut GROUP BY correct ou pas ?
    Bonjour,

    Cette discussion fait suite à une précédente.

    Pour rappel, je désire compter des logements par immeuble et par année.

    Dans la précédente discussion, Waldar m'a notamment précisé que si MySQL est permissif sur le GROUP BY, pour les autres SGBD, il fallait inclure l'ensemble des colonnes de la clause SELECT dans le GROUP BY.

    Maintenant, j'ai dû modifier la requête précédente pour une raison métier. En effet, alors que je comptais mes logements en tenant compte de la date de début et fin des immeubles, j'ai pris comme critère les dates de début et fin des logements, le nombre de ceux-ci dans un immeuble pouvant varier au fil des années.

    J'ai donc la requête suivante :

    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
    SELECT cal.ANNEE_REF
        , EXTRACT(YEAR FROM log.DATE_DEBUT)  AS ANNEE_DEBUT
        , EXTRACT(YEAR FROM log.DATE_FIN) AS ANNEE_FIN
        , imm.NUMERO_DOSSIER
        , imm.LETTRE_DOSSIER
        , imm.TYPE_STATUT_IMMEUBLE_ID_FK
        , COUNT(log.ID) AS NB_LOG
    FROM (SELECT DISTINCT EXTRACT(YEAR FROM DATE) AS ANNEE_REF FROM ipc) AS cal
    JOIN immeuble AS imm      
    JOIN logement AS log
    ON log.IMMEUBLE_ID_FK = imm.ID AND cal.ANNEE_REF >= EXTRACT(YEAR FROM log.DATE_DEBUT)
        AND (cal.ANNEE_REF <= EXTRACT(YEAR FROM log.DATE_FIN)-1 OR log.DATE_FIN IS NULL)
    WHERE imm.TYPE_STATUT_IMMEUBLE_ID_FK >= 3
    GROUP BY cal.ANNEE_REF
        , EXTRACT(YEAR FROM log.DATE_DEBUT)
        , EXTRACT(YEAR FROM log.DATE_FIN)
        , imm.NUMERO_DOSSIER
        , imm.LETTRE_DOSSIER
        , imm.TYPE_STATUT_IMMEUBLE_ID_FK
    ORDER BY cal.ANNEE_REF ASC
        , imm.NUMERO_DOSSIER ASC
        , imm.LETTRE_DOSSIER ASC;
    Elle ne fonctionne pas vraiment de la manière attendue. En effet, tant qu'aucun logement n'a de date de fin renseignée, j'ai bien le résultat que je désire :

    1984 1000 26
    1985 1000 26
    1986 1000 26
    1987 1000 26
    etc...

    Par contre, si je renseigne une date fin d'un logement, j'obtiens ceci :

    1984 1000 25
    1984 1000 1
    1985 1000 25
    1985 1000 1
    1986 1000 25 <== ici, un logement en moins, ce qui est correct.
    1987 1000 25
    etc...

    Si je supprime les dates de début et fin des logements du GROUP BY, j'ai bien le résultat que je désire obtenir .

    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 cal.ANNEE_REF
        , EXTRACT(YEAR FROM log.DATE_DEBUT)  AS ANNEE_DEBUT
        , EXTRACT(YEAR FROM log.DATE_FIN) AS ANNEE_FIN
        , imm.NUMERO_DOSSIER
        , imm.LETTRE_DOSSIER
        , imm.TYPE_STATUT_IMMEUBLE_ID_FK
        , COUNT(log.ID) AS NB_LOG
    FROM (SELECT DISTINCT EXTRACT(YEAR FROM DATE) AS ANNEE_REF FROM ipc) AS cal
    JOIN immeuble AS imm      
    JOIN logement AS log
    ON log.IMMEUBLE_ID_FK = imm.ID AND cal.ANNEE_REF >= EXTRACT(YEAR FROM log.DATE_DEBUT)
        AND (cal.ANNEE_REF <= EXTRACT(YEAR FROM log.DATE_FIN)-1 OR log.DATE_FIN IS NULL)
    WHERE imm.TYPE_STATUT_IMMEUBLE_ID_FK >= 3
    GROUP BY cal.ANNEE_REF
        , imm.NUMERO_DOSSIER
        , imm.LETTRE_DOSSIER
        , imm.TYPE_STATUT_IMMEUBLE_ID_FK
    ORDER BY cal.ANNEE_REF ASC
        , imm.NUMERO_DOSSIER ASC
        , imm.LETTRE_DOSSIER ASC;
    Ma question est la suivante. La bonne pratique du SQL autorise-t-elle de sciemment ignorer certaines colonnes de la clause SELECT dans le GROUP BY, dès lors qu'on en connaît l'effet dans le résultat ?

    Ou bien faudrait-il écrire cette requête différemment ?

    Merci d'avance.

  2. #2
    Expert éminent sénior
    Homme Profil pro
    Responsable Données
    Inscrit en
    Janvier 2009
    Messages
    5 285
    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 285
    Points : 12 987
    Points
    12 987
    Par défaut
    Bonjour,
    Citation Envoyé par Domi2 Voir le message
    Ma question est la suivante. La bonne pratique du SQL autorise-t-elle de sciemment ignorer certaines colonnes de la clause SELECT dans le GROUP BY, dès lors qu'on en connaît l'effet dans le résultat ?
    A part avec MySQL qui s'assoit sur les normes est permissif, tout ce qui est dans la clause select et qui ne fait pas l'objet d'une fonction d'agrégation DOIT se retrouver dans la clause GROUP-BY.

    Par contre il me semble que les requêtes ne correspondent pas aux résultats présentés: 7 colonnes dans les select, contre 3 dans les résultats.

    Tatayo.

  3. #3
    Expert éminent sénior
    Avatar de Domi2
    Homme Profil pro
    Gestionnaire
    Inscrit en
    Juin 2006
    Messages
    7 194
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 64
    Localisation : Suisse

    Informations professionnelles :
    Activité : Gestionnaire
    Secteur : Administration - Collectivité locale

    Informations forums :
    Inscription : Juin 2006
    Messages : 7 194
    Points : 16 044
    Points
    16 044
    Par défaut
    Bonjour,

    Si tu parles de ceci, effectivement, j'ai simplifié pour n'afficher que les trois colonnes importantes du résultat :

    Citation Envoyé par Domi2 Voir le message
    1984 1000 25
    1984 1000 1
    1985 1000 25
    1985 1000 1
    1986 1000 25 <== ici, un logement en moins, ce qui est correct.
    1987 1000 25
    etc...
    En vrai, j'ai bien sept colonnes dans le résultat.

    Donc si je te comprend bien, ma requête est tout sauf parfaite, mais elle fonctionne avec MySQL.

    Comment pourrait-on la normaliser au mieux ?

  4. #4
    Expert éminent sénior
    Homme Profil pro
    Responsable Données
    Inscrit en
    Janvier 2009
    Messages
    5 285
    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 285
    Points : 12 987
    Points
    12 987
    Par défaut
    En fait il faut savoir quelle valeur garder pour les colonnes qui ne sont pas dans la clause group-by. La plus petite, la plus grande, la moyenne... quand on laisse MySql choisir, comment savoir ce qui sera renvoyé ?
    D'où m remarque sur les exemples donnés.

    Tatayo

  5. #5
    Expert éminent sénior
    Avatar de Domi2
    Homme Profil pro
    Gestionnaire
    Inscrit en
    Juin 2006
    Messages
    7 194
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 64
    Localisation : Suisse

    Informations professionnelles :
    Activité : Gestionnaire
    Secteur : Administration - Collectivité locale

    Informations forums :
    Inscription : Juin 2006
    Messages : 7 194
    Points : 16 044
    Points
    16 044
    Par défaut
    Bonjour,

    Et bien sur les sept colonnes, j'ai besoin pour l'instant de trois valeurs.

    imm.NUMERO_DOSSIER
    imm.LETTRE_DOSSIER
    COUNT(log.ID) AS NB_LOG
    Cela fonctionne avec la requête que j'ai actuellement, mais dans la mesure du possible, je désire que celle-ci soit améliorée pour que sa syntaxe soit vraiment correcte.

  6. #6
    Expert éminent sénior
    Homme Profil pro
    Responsable Données
    Inscrit en
    Janvier 2009
    Messages
    5 285
    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 285
    Points : 12 987
    Points
    12 987
    Par défaut
    Dans ce cas c'est plus simple:
    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
     
    SELECT imm.NUMERO_DOSSIER
        , imm.LETTRE_DOSSIER
        , imm.TYPE_STATUT_IMMEUBLE_ID_FK
        , COUNT(log.ID) AS NB_LOG
    FROM (SELECT DISTINCT EXTRACT(YEAR FROM DATE) AS ANNEE_REF FROM ipc) AS cal
    JOIN immeuble AS imm      
    JOIN logement AS log
    ON log.IMMEUBLE_ID_FK = imm.ID AND cal.ANNEE_REF >= EXTRACT(YEAR FROM log.DATE_DEBUT)
        AND (cal.ANNEE_REF <= EXTRACT(YEAR FROM log.DATE_FIN)-1 OR log.DATE_FIN IS NULL)
    WHERE imm.TYPE_STATUT_IMMEUBLE_ID_FK >= 3
    GROUP BY imm.NUMERO_DOSSIER
        , imm.LETTRE_DOSSIER
    ORDER BY imm.NUMERO_DOSSIER ASC
        , imm.LETTRE_DOSSIER ASC;

    La syntaxe est correcte, mais du coup la date a disparu .

    Tatayo.

  7. #7
    Expert éminent sénior
    Avatar de Domi2
    Homme Profil pro
    Gestionnaire
    Inscrit en
    Juin 2006
    Messages
    7 194
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 64
    Localisation : Suisse

    Informations professionnelles :
    Activité : Gestionnaire
    Secteur : Administration - Collectivité locale

    Informations forums :
    Inscription : Juin 2006
    Messages : 7 194
    Points : 16 044
    Points
    16 044
    Par défaut
    C'est bien le résultat auquel je suis finalement arrivé.

    Reste effectivement le problème de la date. Je n'en ai pas absolument besoin dans ce contexte précis, c'est juste que je cherche à essayer de bien comprendre.

    Je vais passer cette discussion en résolu, parce qu'il a été répondu à ma question initiale.

    Merci.

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

Discussions similaires

  1. [MySQL] Script blocant l'accès à intervalle d'une heure, code correct ou pas ?
    Par Overstone dans le forum PHP & Base de données
    Réponses: 1
    Dernier message: 06/08/2007, 10h03
  2. Réponses: 10
    Dernier message: 19/07/2007, 23h37
  3. [WiFi] IP correcte, mais pas de connexion au net
    Par gangsoleil dans le forum Windows Vista
    Réponses: 4
    Dernier message: 19/07/2007, 16h03
  4. Gestion mémoire correcte ou pas ?
    Par vandamme dans le forum C++
    Réponses: 11
    Dernier message: 04/07/2007, 02h45
  5. Selection de Groupes ki ne sont pas sous groupes...
    Par superdada dans le forum Langage SQL
    Réponses: 2
    Dernier message: 23/07/2003, 15h42

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