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

Requêtes MySQL Discussion :

Question sur la mise en ordre du resultat d'un requete


Sujet :

Requêtes MySQL

  1. #1
    Futur Membre du Club
    Profil pro
    Inscrit en
    Septembre 2003
    Messages
    10
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2003
    Messages : 10
    Points : 5
    Points
    5
    Par défaut Question sur la mise en ordre du resultat d'un requete
    J'ai 2 tables

    Une Table "Pnj"

    Avec comme champs :
    "id","zone",....
    ... = le reste est inutile pour la question

    Une Table "Pnj_nom"

    Avec comme champs :

    "id_pnj","lng","nom"
    Un "Pnj" peut avoir un "nom" différent par langue

    dans la table "Pnj" on a :
    "1", "3"
    dans la table "Pnj_nom" on peut avoir des données de ce type la :
    "1", "fr", "Toto"
    "1", "en", "Titi"
    En fonction de la langue de l'utilisateur J'affiche le nom dans sa langue, Si le nom n'est pas renseigner j'affiche le nom "fr" par defaut.

    J'ai découvert ici les joies de GROUP_CONCAT et des jointures pour m'eviter certaines boucles en php.

    Donc j'ai fait cette requete :

    SELECT d.id, GROUP_CONCAT(e.nom) as nom, d.zone FROM Pnj d INNER JOIN Pnj_lng e ON d.id = e.id_pnj WHERE d.zone='3' GROUP BY d.nom ORDER BY e.nom
    Qui me permet d'avoir dans le résultat :

    nom = Titi, Toto


    Premiere question est-ce que ma requete est correcte ? (Est-ce que je complique les choses pour rien, vu que je debute dans l'utilisation de GROUP_CONCAT)

    Ai-je une solution pour que la concaténation soit ordonné avec en premier la langue de l'utilisateur ?

  2. #2
    Futur Membre du Club
    Profil pro
    Inscrit en
    Septembre 2003
    Messages
    10
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2003
    Messages : 10
    Points : 5
    Points
    5
    Par défaut
    Apres lecture des documentations sur le site j'ai trouvé une solution bien plus interessante, pour mon cas.

  3. #3
    Rédacteur/Modérateur

    Avatar de Antoun
    Homme Profil pro
    Architecte décisionnel
    Inscrit en
    Octobre 2006
    Messages
    6 281
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 53
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Architecte décisionnel
    Secteur : Conseil

    Informations forums :
    Inscription : Octobre 2006
    Messages : 6 281
    Points : 11 737
    Points
    11 737
    Par défaut
    Premiere question est-ce que ma requete est correcte ?
    GROUP BY d.nom m'étonne, il me semblait que tu n'avais pas de colonne nom dans pnj...
    Ai-je une solution pour que la concaténation soit ordonné avec en premier la langue de l'utilisateur ?
    GROUP_CONCAT(e.nom ORDER BY e.lng)
    Antoun
    Expert Essbase, BO, SQL

    La bible d'Essbase, 2ème édition

  4. #4
    Futur Membre du Club
    Profil pro
    Inscrit en
    Septembre 2003
    Messages
    10
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2003
    Messages : 10
    Points : 5
    Points
    5
    Par défaut
    Citation Envoyé par Antoun
    GROUP BY d.nom m'étonne, il me semblait que tu n'avais pas de colonne nom dans pnj...
    GROUP BY d.id est plus logique je presume

    d.nom a l'air de fonctionner quand même (Ne serait-ce pas a cause du "AS nom" du GROUP_CONCAT ?)


    Citation Envoyé par Antoun
    GROUP_CONCAT(e.nom ORDER BY e.lng)
    Cela n'a aucune incidence dans ma requete, vue que dans mon exemple on aura toujours :
    nom = Titi, Toto

    Que ce cas correspond à la langue "en" de l'utilisateur.

    Or si la langue de l'utilisateur est "fr" j'aurai voulu avoir

    nom= Toto, Titi

  5. #5
    Rédacteur/Modérateur

    Avatar de Antoun
    Homme Profil pro
    Architecte décisionnel
    Inscrit en
    Octobre 2006
    Messages
    6 281
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 53
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Architecte décisionnel
    Secteur : Conseil

    Informations forums :
    Inscription : Octobre 2006
    Messages : 6 281
    Points : 11 737
    Points
    11 737
    Par défaut
    hypothèse 1 : Si tu veux ordonner les langues, par exemple dire que tu veux toujours le français en premier, puis l'anglais, puis l'espagnol, etc... tu ajoutes une table des langues :

    lng ordre
    ----------
    fr 1
    en 2
    es 3

    Dans ta requêtes, tu jointures sur cette table et tu fais ton GROUP_CONCAT(... ORDER BY langues.ordre).

    hypothèse 2 : tu veux un seul nom et non une liste de noms, de préférence celui qui est dans la langue de l'utilisateur, en français si ce n'est pas possible. Dans ce cas, ce que tu veux n'est pas un GROUP_CONCAT mais un COALESCE. Pour un utilisateur anglophone, cela donne :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
     
    SELECT d.id, COALESCE(f.nom, e.nom) as nom, d.zone
    FROM Pnj d 
      INNER JOIN Pnj_lng f -- tous les pnj ont un nom français
         ON d.id = f.id_pnj AND f.lng = 'fr'
      LEFT JOIN Pnj_lng e -- les pnj n'ont pas tj de nom anglais
        ON d.id = e.id_pnj AND f.lng = 'en'
    WHERE d.zone='3' 
    GROUP BY d.id
    ORDER BY e.nom
    Antoun
    Expert Essbase, BO, SQL

    La bible d'Essbase, 2ème édition

  6. #6
    Futur Membre du Club
    Profil pro
    Inscrit en
    Septembre 2003
    Messages
    10
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2003
    Messages : 10
    Points : 5
    Points
    5
    Par défaut
    Merci beaucoup je n'avais pas encore vu "COALESCE()". Et cela va certainement m'apporter pas mal de chose interessante pour mon site .

  7. #7
    Futur Membre du Club
    Profil pro
    Inscrit en
    Septembre 2003
    Messages
    10
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2003
    Messages : 10
    Points : 5
    Points
    5
    Par défaut
    Citation Envoyé par Antoun
    SELECT d.id, COALESCE(f.nom, e.nom) as nom, d.zone
    FROM Pnj d
    INNER JOIN Pnj_lng f -- tous les pnj ont un nom français
    ON d.id = f.id_pnj AND f.lng = 'fr'
    LEFT JOIN Pnj_lng e -- les pnj n'ont pas tj de nom anglais
    ON d.id = e.id_pnj AND f.lng = 'en'
    WHERE d.zone='3'
    GROUP BY d.id
    ORDER BY e.nom
    N'a pas fonctionner correctement donc j'en suis arriver à cela :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    SELECT d.id, e.nom, d.screen, d.lvl_min, d.lvl_max, d.type, d.zone, d.user_id, f.loc, count(f.loc) as nb_loc
    	FROM Pnj d 
    	INNER JOIN Pnj_lng e ON d.id = e.id_pnj AND (e.lng = 'en' OR e.lng = 'fr') 
    	INNER JOIN Pnj_loc f ON d.id = f.id_pnj 
    	WHERE d.zone = '3'
    	GROUP BY d.id 
    	ORDER BY e.nom
    Pour le cas d'un utilisateur anglais.

    Je presume que ca ne fait pas tres propre si le 'en' devient un 'fr'. pour le cas d'un utilisateur français

  8. #8
    Rédacteur/Modérateur

    Avatar de Antoun
    Homme Profil pro
    Architecte décisionnel
    Inscrit en
    Octobre 2006
    Messages
    6 281
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 53
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Architecte décisionnel
    Secteur : Conseil

    Informations forums :
    Inscription : Octobre 2006
    Messages : 6 281
    Points : 11 737
    Points
    11 737
    Par défaut
    Citation Envoyé par Kaar
    N'a pas fonctionner correctement
    Qu'est-ce que ça fait ?
    Citation Envoyé par Kaar
    donc j'en suis arriver à cela :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    ...
    INNER JOIN Pnj_lng e ON d.id = e.id_pnj AND (e.lng = 'en' OR e.lng = 'fr')
    e.lng IN ('en', 'fr') doit être légèrement plus rapide.
    Citation Envoyé par Kaar
    Je presume que ca ne fait pas tres propre si le 'en' devient un 'fr'. pour le cas d'un utilisateur français
    du moment que ça marche... mais je doute que ce soit le cas. Ton utilisation d'une seule instance de pnj_lng va faire que le nom français et le nom anglais sont sur deux lignes ; en gros cela crée un doublon. En utilisant GROUP BY d.ID, tu indiques à MySQL de prendra la première valeur qu'il trouve pour les colonnes non agrégées du SELECT, à savoir d.id, e.nom, d.screen, d.lvl_min, d.lvl_max, d.type, d.zone, d.user_id et f.loc. Le résultat est qu'il te donnera aléatoirement le nom français ou le nom anglais, selon celui qui est le premier dans l'ordre physique de la table.
    Antoun
    Expert Essbase, BO, SQL

    La bible d'Essbase, 2ème édition

  9. #9
    Futur Membre du Club
    Profil pro
    Inscrit en
    Septembre 2003
    Messages
    10
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2003
    Messages : 10
    Points : 5
    Points
    5
    Par défaut
    Citation Envoyé par Antoun
    Qu'est-ce que ça fait ?
    Cela ne sort que les nom en français quoi qu'il arrive

    Citation Envoyé par Antoun
    e.lng IN ('en', 'fr') doit être légèrement plus rapide.
    J'ai tester ce n'est pas flagrant mais le format allege toujours un peu la requete

    Citation Envoyé par Antoun
    du moment que ça marche... mais je doute que ce soit le cas. Ton utilisation d'une seule instance de pnj_lng va faire que le nom français et le nom anglais sont sur deux lignes ; en gros cela crée un doublon. En utilisant GROUP BY d.ID, tu indiques à MySQL de prendra la première valeur qu'il trouve pour les colonnes non agrégées du SELECT, à savoir d.id, e.nom, d.screen, d.lvl_min, d.lvl_max, d.type, d.zone, d.user_id et f.loc. Le résultat est qu'il te donnera aléatoirement le nom français ou le nom anglais, selon celui qui est le premier dans l'ordre physique de la table.
    dans "AND (e.lng = 'en' OR e.lng = 'fr') " ne va t'il pas dans un premier temps rechercher e.lng = 'en' et au resultat y ajouter e.lng = 'fr' donc le 'fr' forcement apres le 'en' ? Et le 'GROUP BY d.id' vu que dans le resultat le nom en 'en' et le nom en 'fr' ont le même id cela fait disparaitre le nom en 'fr' s'il y a un nom en 'en'

    Enfin je le vois comme ca . Physiquement le nom 'fr' est et sera toujours en premier dans la table Pnj_lng.

  10. #10
    Rédacteur/Modérateur

    Avatar de Antoun
    Homme Profil pro
    Architecte décisionnel
    Inscrit en
    Octobre 2006
    Messages
    6 281
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 53
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Architecte décisionnel
    Secteur : Conseil

    Informations forums :
    Inscription : Octobre 2006
    Messages : 6 281
    Points : 11 737
    Points
    11 737
    Par défaut
    Cela ne sort que les nom en français quoi qu'il arrive
    désolé je t'ai dit COALESCE(f.nom, e.nom), mais c'est le contraire qu'il te faut : COALESCE(e.nom, f.nom).
    Antoun
    Expert Essbase, BO, SQL

    La bible d'Essbase, 2ème édition

  11. #11
    Futur Membre du Club
    Profil pro
    Inscrit en
    Septembre 2003
    Messages
    10
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2003
    Messages : 10
    Points : 5
    Points
    5
    Par défaut
    Citation Envoyé par Antoun
    désolé je t'ai dit COALESCE(f.nom, e.nom), mais c'est le contraire qu'il te faut : COALESCE(e.nom, f.nom).
    Même résultat

  12. #12
    Rédacteur/Modérateur

    Avatar de Antoun
    Homme Profil pro
    Architecte décisionnel
    Inscrit en
    Octobre 2006
    Messages
    6 281
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 53
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Architecte décisionnel
    Secteur : Conseil

    Informations forums :
    Inscription : Octobre 2006
    Messages : 6 281
    Points : 11 737
    Points
    11 737
    Par défaut
    coquilles & pétouilles...
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    SELECT d.id, COALESCE(e.nom, f.nom) as nom, d.zone
     FROM Pnj d
     INNER JOIN Pnj_lng f 
     ON d.id = f.id_pnj AND f.lng = 'fr'
     LEFT JOIN Pnj_lng e 
     ON d.id = e.id_pnj AND e.lng = 'en'
     WHERE d.zone='3'
    -- à supprimer  GROUP BY d.id
     ORDER BY 2
    Antoun
    Expert Essbase, BO, SQL

    La bible d'Essbase, 2ème édition

  13. #13
    Rédacteur/Modérateur

    Avatar de Antoun
    Homme Profil pro
    Architecte décisionnel
    Inscrit en
    Octobre 2006
    Messages
    6 281
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 53
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Architecte décisionnel
    Secteur : Conseil

    Informations forums :
    Inscription : Octobre 2006
    Messages : 6 281
    Points : 11 737
    Points
    11 737
    Par défaut
    dans "AND (e.lng = 'en' OR e.lng = 'fr') " ne va t'il pas dans un premier temps rechercher e.lng = 'en' et au resultat y ajouter e.lng = 'fr' donc le 'fr' forcement apres le 'en' ?
    non, PHP fonctionnerait comme ça, mais SQL est ensembliste et non procédural. Autrement dit, le OR n'implique pas pas de priorité. Si les 2 existent, MySQL prendra donc les 2 et ce sera ensuite au GROUP BY de résoudre le doublon. En l'occurence, tu indiques à MySQL que le nom est supposé unique pour une ID donnée, et qu'il peut donc prendre le nom qui l'arrange (tous les autres SGBD refuseraient ta requête par peur d'une incohérence).

    Enfin je le vois comme ca . Physiquement le nom 'fr' est et sera toujours en premier dans la table Pnj_lng.
    non, parce que l'ordre de la table est un choix de l'optimiseur, et n'est soumis à aucune contrainte logique. Si par exemple tu as des suppressions, les lignes que tu ajouteras ensuite pourront venir combler les trous laissés par les suppressions.
    Au niveau logique, le principe ensembliste est "il n'y a pas plus d'ordre des lignes dans une table que d'ordre des billes dans un sac."
    Antoun
    Expert Essbase, BO, SQL

    La bible d'Essbase, 2ème édition

  14. #14
    Futur Membre du Club
    Profil pro
    Inscrit en
    Septembre 2003
    Messages
    10
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2003
    Messages : 10
    Points : 5
    Points
    5
    Par défaut
    Ok j'aurai appris pas mal de choses et ca marche merci beaucoup.

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

Discussions similaires

  1. question sur la mise en place d'une architecture glpi oracle
    Par sousoujda2 dans le forum Langage SQL
    Réponses: 1
    Dernier message: 17/08/2008, 16h07
  2. Réponses: 2
    Dernier message: 07/03/2008, 10h29
  3. Question sur la mise en forme
    Par Mike888 dans le forum EDI et Outils pour Java
    Réponses: 1
    Dernier message: 07/06/2007, 17h46
  4. [XHTML|CSS] Question sur la mise en page
    Par stilobique dans le forum Balisage (X)HTML et validation W3C
    Réponses: 4
    Dernier message: 11/03/2007, 18h09

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