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 :

Requête mysql avec tables d'associations


Sujet :

Requêtes MySQL

  1. #1
    Candidat au Club
    Profil pro
    Inscrit en
    Juillet 2010
    Messages
    11
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juillet 2010
    Messages : 11
    Points : 4
    Points
    4
    Par défaut Requête mysql avec tables d'associations
    Bonjour,

    Je m'initie (non sans mal) à MySQL (et autre) et je suis en train de développer un petit projet perso (en local pour moi, donc sans trop se poser des questions de sécurité) et je suis tombé sur un "petit" os ... pour vous l'expliquer, il faudrait que je rentre dans le détails de ma base de données, comment celle-ci doit fonctionner et ça prendrais pas mal de temps. Donc j'ai décidé de prendre un exemple plus simple pour vous exposer mon petit "souci"...

    Un graph vaut mieux que de long discours :


    Dans cette base, des utilisateurs peuvent aimer une ou plusieurs couleurs, conduire un ou plusieurs véhicules et détester un ou plusieurs fromages ...

    Les tables d'associations contiennent donc une ou plusieurs lignes pour chaque utilisateur. Dans chaque table, ligne associe l'id_user avec un (ou plusieurs) id_couleur, id_vehicule et id_fromage.

    Le code SQL est le suivant :
    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
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
     
    -- ---
    -- Table 'user'
    -- ---
     
    DROP TABLE IF EXISTS `user`;
     
    CREATE TABLE `user` (
      `id` TINYINT NULL AUTO_INCREMENT DEFAULT NULL,
      `nom_user` VARCHAR(100) NULL DEFAULT NULL,
      PRIMARY KEY (`id`)
    );
     
    -- ---
    -- Table 'couleur'
    -- ---
     
    DROP TABLE IF EXISTS `couleur`;
     
    CREATE TABLE `couleur` (
      `id` TINYINT NULL AUTO_INCREMENT DEFAULT NULL,
      `nom_couleur` VARCHAR(100) NULL DEFAULT NULL,
      PRIMARY KEY (`id`)
    );
     
    -- ---
    -- Table 'vehicule'
    -- ---
     
    DROP TABLE IF EXISTS `vehicule`;
     
    CREATE TABLE `vehicule` (
      `id` TINYINT NULL AUTO_INCREMENT DEFAULT NULL,
      `nom_vehicule` VARCHAR(100) NULL DEFAULT NULL,
      PRIMARY KEY (`id`)
    );
     
    -- ---
    -- Table 'fromage'
    -- ---
     
    DROP TABLE IF EXISTS `fromage`;
     
    CREATE TABLE `fromage` (
      `id` TINYINT NULL AUTO_INCREMENT DEFAULT NULL,
      `nom_fromage` VARCHAR(100) NULL DEFAULT NULL,
      PRIMARY KEY (`id`)
    );
     
    -- ---
    -- Table 'aime'
    -- ---
     
    DROP TABLE IF EXISTS `aime`;
     
    CREATE TABLE `aime` (
      `id` TINYINT NULL AUTO_INCREMENT DEFAULT NULL,
      `id_user` TINYINT NULL DEFAULT NULL,
      `id_couleur` TINYINT NULL DEFAULT NULL,
      PRIMARY KEY (`id`)
    );
     
    -- ---
    -- Table 'conduit'
    -- ---
     
    DROP TABLE IF EXISTS `conduit`;
     
    CREATE TABLE `conduit` (
      `id` TINYINT NULL AUTO_INCREMENT DEFAULT NULL,
      `id_user` TINYINT NULL DEFAULT NULL,
      `id_vehicule` TINYINT NULL DEFAULT NULL,
      PRIMARY KEY (`id`)
    );
     
    -- ---
    -- Table 'deteste'
    -- ---
     
    DROP TABLE IF EXISTS `deteste`;
     
    CREATE TABLE `deteste` (
      `id` TINYINT NULL AUTO_INCREMENT DEFAULT NULL,
      `id_user` TINYINT NULL DEFAULT NULL,
      `id_fromage` TINYINT NULL DEFAULT NULL,
      PRIMARY KEY (`id`)
    );
     
    -- ---
    -- Foreign Keys 
    -- ---
     
    ALTER TABLE `aime` ADD FOREIGN KEY (id_user) REFERENCES `user` (`id`);
    ALTER TABLE `aime` ADD FOREIGN KEY (id_couleur) REFERENCES `couleur` (`id`);
    ALTER TABLE `conduit` ADD FOREIGN KEY (id_user) REFERENCES `user` (`id`);
    ALTER TABLE `conduit` ADD FOREIGN KEY (id_vehicule) REFERENCES `vehicule` (`id`);
    ALTER TABLE `deteste` ADD FOREIGN KEY (id_user) REFERENCES `user` (`id`);
    ALTER TABLE `deteste` ADD FOREIGN KEY (id_fromage) REFERENCES `fromage` (`id`);
     
    -- ---
    -- Test Data
    -- ---
     
    INSERT INTO `user` (`nom_user`) VALUES
    ('Marie'),('John'),('Robert'),('Stéphanie');
    INSERT INTO `couleur` (`nom_couleur`) VALUES
    ('Bleu'),('Rouge'),('Vert'),('Marron'),('Jaune'),('Violet');
    INSERT INTO `vehicule` (`nom_vehicule`) VALUES
    ('306'),('Mini'),('Vélib'),('F16'),('Ferrari'),('Porsche');
    INSERT INTO `fromage` (`nom_fromage`) VALUES
    ('Camembert'),('Roquefort'),('Comté'),('Tome'),('Chèvre');
    INSERT INTO `aime` (`id_user`,`id_couleur`) VALUES
    ('1','1'),('1','3'),('1','6'),('2','2'),('3','4'),('3','5'),('3','6'),('4','1'),('4','2'),('4','3'),('4','5'),('4','6');
    INSERT INTO `conduit` (`id_user`,`id_vehicule`) VALUES
    ('1','4'),('1','2'),('2','1'),('2','2'),('2','5'),('2','6'),('3','3'),('3','4'),('4','2'),('4','3'),('4','5'),('4','6');
    INSERT INTO `deteste` (`id_user`,`id_fromage`) VALUES
    ('1','1'),('1','2'),('1','3'),('1','4'),('1','5'),('2','5'),('3','1'),('3','5'),('4','1'),('4','2'),('4','3'),('4','4');
    Jusqu'à là tout va bien ...

    Maintenant la requête pour sélectionner l'utilisateur 3 (par exemple ROBERT) :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
     
    SELECT u.nom_user, c.nom_couleur, v.nom_vehicule, f.nom_fromage
    FROM user u
    INNER JOIN aime a ON a.id_user = u.id
    INNER JOIN conduit k ON k.id_user = u.id
    INNER JOIN deteste d ON d.id_user = u.id
    INNER JOIN couleur c ON c.id = a.id_couleur
    INNER JOIN vehicule v ON v.id = k.id_vehicule
    INNER JOIN fromage f ON f.id = d.id_fromage
    WHERE u.id =3
    Super j'ai une belle réponse, mais une sacré réponse : 12 LIGNES !!!!!!! Une combinaison de chacune de ses associations :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
     
    Robert  Marron  Vélib  Camembert
    Robert  Jaune   Vélib  Camembert
    Robert  Violet  Vélib  Camembert
    Robert  Marron  Vélib  Chèvre
    Robert  Jaune   Vélib  Chèvre
    Robert  Violet  Vélib  Chèvre
    Robert  Marron  F16    Camembert
    Robert  Jaune   F16    Camembert
    Robert  Violet  F16    Camembert
    Robert  Marron  F16    Chèvre
    Robert  Jaune   F16    Chèvre
    Robert  Violet  F16    Chèvre
    C'est génial sauf qu'en PHP je me retrouve avec un beau tableau comme celui-là :
    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
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
     
    Array
    (
        [0] => Array
            (
                [nom_user] => Robert
                [nom_couleur] => Marron
                [nom_vehicule] => Vélib
                [nom_fromage] => Camembert
            )
     
        [1] => Array
            (
                [nom_user] => Robert
                [nom_couleur] => Jaune
                [nom_vehicule] => Vélib
                [nom_fromage] => Camembert
            )
     
        [2] => Array
            (
                [nom_user] => Robert
                [nom_couleur] => Violet
                [nom_vehicule] => Vélib
                [nom_fromage] => Camembert
            )
     
        [3] => Array
            (
                [nom_user] => Robert
                [nom_couleur] => Marron
                [nom_vehicule] => Vélib
                [nom_fromage] => Chèvre
            )
     
        [4] => Array
            (
                [nom_user] => Robert
                [nom_couleur] => Jaune
                [nom_vehicule] => Vélib
                [nom_fromage] => Chèvre
            )
     
        [5] => Array
            (
                [nom_user] => Robert
                [nom_couleur] => Violet
                [nom_vehicule] => Vélib
                [nom_fromage] => Chèvre
            )
     
        [6] => Array
            (
                [nom_user] => Robert
                [nom_couleur] => Marron
                [nom_vehicule] => F16
                [nom_fromage] => Camembert
            )
     
        [7] => Array
            (
                [nom_user] => Robert
                [nom_couleur] => Jaune
                [nom_vehicule] => F16
                [nom_fromage] => Camembert
            )
     
        [8] => Array
            (
                [nom_user] => Robert
                [nom_couleur] => Violet
                [nom_vehicule] => F16
                [nom_fromage] => Camembert
            )
     
        [9] => Array
            (
                [nom_user] => Robert
                [nom_couleur] => Marron
                [nom_vehicule] => F16
                [nom_fromage] => Chèvre
            )
     
        [10] => Array
            (
                [nom_user] => Robert
                [nom_couleur] => Jaune
                [nom_vehicule] => F16
                [nom_fromage] => Chèvre
            )
     
        [11] => Array
            (
                [nom_user] => Robert
                [nom_couleur] => Violet
                [nom_vehicule] => F16
                [nom_fromage] => Chèvre
            )
     
    )
    Le code php pour obtenir cela :
    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
     
    <?php
    include('Database.php'); //Web: http://www.ricocheting.com/
    define('DB_SERVER', 'localhost');
    define('DB_USER', 'root');
    define('DB_PASS', 'monmotdepasse');
    define('DB_DATABASE', 'plop');
    $db = new Database(DB_SERVER, DB_USER, DB_PASS, DB_DATABASE);
    $db->connect();
     
    $sql = "select u.nom_user,c.nom_couleur,v.nom_vehicule,f.nom_fromage from user u\n"
        . "inner join aime a on a.id_user=u.id\n"
        . "inner join conduit k on k.id_user=u.id\n"
        . "inner join deteste d on d.id_user=u.id\n"
        . "inner join couleur c on c.id=a.id_couleur\n"
        . "inner join vehicule v on v.id=k.id_vehicule\n"
        . "inner join fromage f on f.id=d.id_fromage\n"
        . "where u.id=3";
     
    print_r($db->fetch_all_array($sql));
    ?>

    Y'a-t-il moyen d'obtenir, à l'aide de mysql ou php, un tableau avec UNE SEULE LIGNE ? :
    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
    23
    24
     
    Array
    (
        [0] => Array
            (
                [nom_user] => Robert
                [nom_couleur] => Array
    					(
    					[0] => Marron
    					[1] => Jaune
    					[2] => Violet
    					)
                [nom_vehicule] => Array
    					(
    					[0] => Vélib
    					[1] => F16
    					)
                [nom_fromage] => Array
    					(
    					[0] => Chèvre
    					[1] => Camembert
    					)
            )
    )
    Si je dois traiter le premier tableau à l'aide d'un algorithme en PHP, j'ai peur que la complexité et le nombre de ligne dans la table fasse que le traitement soit vraiment lourd et peu optimisé.

    Je me dis aussi que je dois pas être le premier à tomber sur un cas pareil et qu'une fonction (en PHP) ou requête m'a échappée ...

    J'ai essayé de documenter ce post le plus possible pour que si d'autre se pose la question, il trouve la réponse ici (si bien sûr l'un d'entre vous veuille bien se pencher sur le sujet)

    D'avance merci de m'avoir lu et de vos réponses

  2. #2
    Modérateur

    Avatar de CinePhil
    Homme Profil pro
    Ingénieur d'études en informatique
    Inscrit en
    Août 2006
    Messages
    16 799
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 60
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Ingénieur d'études en informatique
    Secteur : Enseignement

    Informations forums :
    Inscription : Août 2006
    Messages : 16 799
    Points : 34 031
    Points
    34 031
    Billets dans le blog
    14
    Par défaut
    Le résultat est normal.
    C'est au programme d'arranger les données pour les présenter, pas au SGBD.
    Donc il faut ordonner le résultat de la requête avec une clause ORDER BY dans la requête puis gérer les ruptures dans le parcours du tableau de résultats en PHP.

    Tu peux aussi faire ceci :
    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
    23
    24
    25
    26
    27
    SELECT tmp.nom_user,
    	tmp.cle,
    	tmp.valeur
    FROM
    (
    	SELECT u1.nom_user,
    		'couleur' AS cle
    		c.nom_couleur AS valeur
    	FROM user u1
    	INNER JOIN aime a ON a.id_user = u1.id
    		INNER JOIN couleur c ON c.id = a.id_couleur
    	UNION
    	SELECT u2.nom_user,
    		'vehicule',
    		v.nom_vehicule
    	FROM user u2
    	INNER JOIN conduit k ON k.id_user = u2.id
    		INNER JOIN vehicule v ON v.id = k.id_vehicule
    	UNION
    	SELECT u3.nom_user,
    		'fromage',
    		f.nom_fromage
    	FROM user u3
    	INNER JOIN deteste d ON d.id_user = u3.id
    		INNER JOIN fromage f ON f.id = d.id_fromage
    ) tmp
    ORDER BY tmp.nom_user, tmp.cle
    Philippe Leménager. Ingénieur d'étude à l'École Nationale Supérieure de Formation de l'Enseignement Agricole. Autoentrepreneur.
    Mon ancien blog sur la conception des BDD, le langage SQL, le PHP... et mon nouveau blog sur les mêmes sujets.
    « Ce que l'on conçoit bien s'énonce clairement, et les mots pour le dire arrivent aisément ». (Nicolas Boileau)
    À la maison comme au bureau, j'utilise la suite Linux Mageïa !

  3. #3
    Membre confirmé
    Homme Profil pro
    Inscrit en
    Juin 2011
    Messages
    445
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Juin 2011
    Messages : 445
    Points : 622
    Points
    622
    Par défaut
    Ce n'est pas la meilleure façon de faire (C'est juste pour te montrer le principe du GROUP_CONCAT ) :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    SELECT u.nom_user, GROUP_CONCAT(DISTINCT c.nom_couleur), GROUP_CONCAT(DISTINCT v.nom_vehicule), GROUP_CONCAT(DISTINCT f.nom_fromage)
    FROM user u
    INNER JOIN aime a ON a.id_user = u.id
    INNER JOIN conduit k ON k.id_user = u.id
    INNER JOIN deteste d ON d.id_user = u.id
    INNER JOIN couleur c ON c.id = a.id_couleur
    INNER JOIN vehicule v ON v.id = k.id_vehicule
    INNER JOIN fromage f ON f.id = d.id_fromage
    WHERE u.id =3

  4. #4
    Candidat au Club
    Profil pro
    Inscrit en
    Juillet 2010
    Messages
    11
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juillet 2010
    Messages : 11
    Points : 4
    Points
    4
    Par défaut
    Merci à vous 2 ... Cela dépasse un peu mon savoir faire ... mais j'apprends !

    Je vais tester tous cela au calme et lire la doc' ...

    Merci particulièrement à CinePhil pour son article sur quand utiliser une table d'association (sur son blog)

    Très instructif, cela a été le point de départ de ma réflexion pour élaborer ma base de données pour mon projet !!

    (quand je vois vos requêtes je me dis que SQL, c'est vraiment un monde à part)

    Je posterais sur ce fil pour d'autres questions

    meeeeeeeeeeeeerci !

  5. #5
    Invité
    Invité(e)
    Par défaut
    Salut,

    Ca me rappelle une de mes questions
    "autres sujet sur le même thème"

    Il y a une requête d'exemple avec group concat si cela peut t'aider.

  6. #6
    Candidat au Club
    Profil pro
    Inscrit en
    Juillet 2010
    Messages
    11
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juillet 2010
    Messages : 11
    Points : 4
    Points
    4
    Par défaut
    bon merci à tous et surtout à FRED 34 qui a su mettre en avant une fonctionnalité intéressante (mais pas évidente à comprendre) de MySQL : GROUP_CONCAT ...

    Si je peux essayer de "traduire" : lorsque dans un SELECT, il y a un GROUP_CONCAT, MySQL va concaténer les résultats du champs spécifié

    Dans mon cas (vu qu'il y a un WHERE u.id=3) les couleurs, fromages et voitures se trouve concaténer (séparés par virgules) ...

    Maintenant, question qui n'attends pas de réponse :
    "Comment faire sans le WHERE ?" ou "Comment obtenir tous les enregistrements ?" ... en effet si je vire le WHERE alors j'ai une seule ligne de résultats avec toutes les couleurs, tous les fromages et toutes les voitures concaténé (1 fois car il y a le DISTINCT) !!!!!

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    Résultat de la requête SQL
     
    Client: localhost
    Base de données: plop
    Généré le: Mer 12 Décembre 2012 à 20:01
    Généré par: phpMyAdmin 3.5.1 / MySQL 5.5.24-log
    Requête SQL: SELECT u.*, GROUP_CONCAT(DISTINCT c.nom_couleur), GROUP_CONCAT(DISTINCT v.nom_vehicule), GROUP_CONCAT(DISTINCT f.nom_fromage) FROM user u INNER JOIN aime a ON a.id_user = u.id INNER JOIN conduit k ON k.id_user = u.id INNER JOIN deteste d ON d.id_user = u.id INNER JOIN couleur c ON c.id = a.id_couleur INNER JOIN vehicule v ON v.id = k.id_vehicule INNER JOIN fromage f ON f.id = d.id_fromage LIMIT 0, 30 ; 
    Lignes: 1
     
    id	nom_user	GROUP_CONCAT(DISTINCT c.nom_couleur)	GROUP_CONCAT(DISTINCT v.nom_vehicule)	GROUP_CONCAT(DISTINCT f.nom_fromage)
    1	Marie		Bleu,Vert,Violet,Marron,Jaune,Rouge	F16,Mini,Vélib,Ferrari,Porsche,306	Camembert,Roquefort,Comté,Tome,Chèvre

    Réponse : Utiliser le GROUP BY

    GROUP BY qui groupe les résultats par ... le champs spécifié (par exemple u.nom ou u.id)

    Ce qui me donne la belle requête ci-dessous (je kiffe le SQL au fait, c'est grave docteur ?) :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    SELECT u.*, GROUP_CONCAT(DISTINCT c.nom_couleur), GROUP_CONCAT(DISTINCT v.nom_vehicule), GROUP_CONCAT(DISTINCT f.nom_fromage)
    FROM user u
    INNER JOIN aime a ON a.id_user = u.id
    INNER JOIN conduit k ON k.id_user = u.id
    INNER JOIN deteste d ON d.id_user = u.id
    INNER JOIN couleur c ON c.id = a.id_couleur
    INNER JOIN vehicule v ON v.id = k.id_vehicule
    INNER JOIN fromage f ON f.id = d.id_fromage
    GROUP BY u.nom_user
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    Résultat de la requête SQL
     
    Client: localhost
    Base de données: plop
    Généré le: Mer 12 Décembre 2012 à 19:54
    Généré par: phpMyAdmin 3.5.1 / MySQL 5.5.24-log
    Requête SQL: SELECT u.*, GROUP_CONCAT(DISTINCT c.nom_couleur), GROUP_CONCAT(DISTINCT v.nom_vehicule), GROUP_CONCAT(DISTINCT f.nom_fromage) FROM user u INNER JOIN aime a ON a.id_user = u.id INNER JOIN conduit k ON k.id_user = u.id INNER JOIN deteste d ON d.id_user = u.id INNER JOIN couleur c ON c.id = a.id_couleur INNER JOIN vehicule v ON v.id = k.id_vehicule INNER JOIN fromage f ON f.id = d.id_fromage GROUP BY u.nom_user LIMIT 0, 30 ; 
    Lignes: 4
     
    id	nom_user	GROUP_CONCAT(DISTINCT c.nom_couleur)	GROUP_CONCAT(DISTINCT v.nom_vehicule)	GROUP_CONCAT(DISTINCT f.nom_fromage)
    2	John		Rouge					Mini,Porsche,306,Ferrari		Chèvre
    1	Marie		Violet,Bleu,Vert			Mini,F16				Chèvre,Camembert,Roquefort,Comté,Tome
    3	Robert		Jaune,Violet,Marron			F16,Vélib				Camembert,Chèvre
    4	Stéphanie	Rouge,Jaune,Violet,Bleu,Vert		Porsche,Vélib,Ferrari,Mini		Camembert,Roquefort,Comté,Tome


    C'est juste super puissant !!!! Si j'avais eu à faire cela en PHP, je vous raconte pas l'horreur ...


    Moi qui avait trouver une jolie feinte dans mon projet pour me passer de ça .... je vais devoir tout "reconstruire" mais ne dis-t-on pas :
    Cent fois sur le métier remets ton ouvrage.
    Meeeeeeeeeeeeeeerci

  7. #7
    Candidat au Club
    Profil pro
    Inscrit en
    Juillet 2010
    Messages
    11
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juillet 2010
    Messages : 11
    Points : 4
    Points
    4
    Par défaut
    Au fait ce GROUP_CONCAT c'est du SQL standard ou c'est spécifique MySQL ?

  8. #8
    Modérateur

    Avatar de CinePhil
    Homme Profil pro
    Ingénieur d'études en informatique
    Inscrit en
    Août 2006
    Messages
    16 799
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 60
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Ingénieur d'études en informatique
    Secteur : Enseignement

    Informations forums :
    Inscription : Août 2006
    Messages : 16 799
    Points : 34 031
    Points
    34 031
    Billets dans le blog
    14
    Par défaut
    Pas SELECT u* mais SELECT u.nom_user car toutes les colonnes du SELECT ne figurant pas dans une fonction de groupage doivent figurer dans le GROUP BY sous peine de récupérer pour les colonnes absentes des résultats aléatoires.

    Dans le cas présent, il est probable que ça n'arrivera pas puisque toutes les colonnes de la table des utilisateurs dépendent directement de son identifiant mais si d'aventure tu ajoutes une jointure vers une autre table pour avoir une autre information, c'est le risque de résultat faux qui pointe le bout de son nez !

    Et GROUP_CONCAT est spécifique MySQL.
    Philippe Leménager. Ingénieur d'étude à l'École Nationale Supérieure de Formation de l'Enseignement Agricole. Autoentrepreneur.
    Mon ancien blog sur la conception des BDD, le langage SQL, le PHP... et mon nouveau blog sur les mêmes sujets.
    « Ce que l'on conçoit bien s'énonce clairement, et les mots pour le dire arrivent aisément ». (Nicolas Boileau)
    À la maison comme au bureau, j'utilise la suite Linux Mageïa !

  9. #9
    Candidat au Club
    Profil pro
    Inscrit en
    Juillet 2010
    Messages
    11
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juillet 2010
    Messages : 11
    Points : 4
    Points
    4
    Par défaut
    Spécifique MySQL ?!! et les autres sql (NoSQL, PostgreSQL, SQL-Server), ils font comment ?

  10. #10
    Candidat au Club
    Profil pro
    Inscrit en
    Juillet 2010
    Messages
    11
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juillet 2010
    Messages : 11
    Points : 4
    Points
    4
    Par défaut
    Oh le bor....del !


    http://mssql-to-postgresql.blogspot....oupconcat.html

    Je retire ma question

  11. #11
    Modérateur

    Avatar de CinePhil
    Homme Profil pro
    Ingénieur d'études en informatique
    Inscrit en
    Août 2006
    Messages
    16 799
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 60
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Ingénieur d'études en informatique
    Secteur : Enseignement

    Informations forums :
    Inscription : Août 2006
    Messages : 16 799
    Points : 34 031
    Points
    34 031
    Billets dans le blog
    14
    Par défaut
    Voilà une explication supposée par SQLPro de l'existence du GROUP_CONCAT, trouvée sur son blog :
    Citation Envoyé par SQLPro
    Le respect des normes est plus important que l’ajout bête et méchant de fonctionnalités inopinées. Prenons le langage SQL, MySQL est le champion de l’ajout de bricolages et cela parce que l’implémentation de la norme demande un travail sérieux et par conséquent couteux. Donc, plutôt que de faire bien, faisons n’importe quoi pour donner l’illusion qu’on est capable de faire la même chose que la concurrence. Les exemples sont nombreux pour MySQL : GROUP_CONCAT pour ne pas avoir implémenté les requêtes récursives
    La norme SQL prévoit le mécanisme des requêtes récursives. Elles existent chez Postgresql mais l'auteur du billet que tu cites ne semble pas avoir voulu ou su les utiliser. À moins qu'elles n'existassent point encore dans Postgresql en 2007, lors de la publication du billet ?
    Philippe Leménager. Ingénieur d'étude à l'École Nationale Supérieure de Formation de l'Enseignement Agricole. Autoentrepreneur.
    Mon ancien blog sur la conception des BDD, le langage SQL, le PHP... et mon nouveau blog sur les mêmes sujets.
    « Ce que l'on conçoit bien s'énonce clairement, et les mots pour le dire arrivent aisément ». (Nicolas Boileau)
    À la maison comme au bureau, j'utilise la suite Linux Mageïa !

  12. #12
    Candidat au Club
    Profil pro
    Inscrit en
    Juillet 2010
    Messages
    11
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juillet 2010
    Messages : 11
    Points : 4
    Points
    4
    Par défaut
    Whooo je viens de lire son billet sur les normes, je suis en partie d'accord avec lui sur le principe qu'une norme est importante à respecter (c'est même pour cela que j'ai posé la question sur la spécificité de GROUP_CONCAT) mais pour faire évoluer un langage (surtout celui obscur de SQL) et qu'il ne reste pas sectaire, il faut des fonctionnalités "facile" d'accès ...

    Moi voulant apprendre le SQL par l'exemple (et mon projet), je n'aurais pas (et ne vais pas) me lancer dans l'utilisation de requêtes récursives mais je vais plutôt utiliser GROUP_CONCAT. Quitte à resté sur MySQL...

    Dans un second temps, si mon projet devient important et doit est interpolable avec d'autre SGBD, alors oui je ferais en sorte qu'il respecte la norme.

    Et s'il lit (SQLPro) ce message, je ne me considère pas comme un "techno-crétin" mais plutôt comme un "techno-intéressé" qui cherche à progresser ...

    Je ne suis pas sûr que son agressivité (sur MySQL par exemple) serve sa cause (respect des normes).

    On pourrait aussi réfléchir à prendre ce qu'il se fait de bien (mais qui ne respecte pas la norme) dans chaque langage pour justement définir une norme plus évoluée ...

    Je remarque, ne venant pas du monde de SQL, qu'un cas d'école comme celui-là amène une solution technique plutôt compliquée s'il l'on veux faire les choses bien (requêtes 'récursives' pour traiter des données avec tables d'associations qui doivent être légion dans l'utilisation de base de données)

  13. #13
    Candidat au Club
    Profil pro
    Inscrit en
    Juillet 2010
    Messages
    11
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juillet 2010
    Messages : 11
    Points : 4
    Points
    4
    Par défaut
    J'ai un doute et excusez moi encore de déterre ce post mais imaginons qu'un utilisateur ne soit pas relie à une table d'association m'a requête ne va pas me le renvoyer ...

    Albert aime le bleu le rouge et le marron, il conduit un velib et un f16 mais aime bien tous les fromages (par d'entrée dans la te le déteste)

    Il ne va pas ressortir dans mes résultats, il existe un moyen en sql de l'inclure dans les résultats de la requête précédente ?

  14. #14
    Candidat au Club
    Profil pro
    Inscrit en
    Juillet 2010
    Messages
    11
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juillet 2010
    Messages : 11
    Points : 4
    Points
    4
    Par défaut
    Requête pour ajouter Albert (id=5):
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    INSERT INTO  user (nom_user)
    VALUES ('Albert');
    requêtes pour ajouter l'entrée dans les tables d'associations :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    INSERT INTO  aime  (id_user ,id_couleur)
    VALUES ('5',  '1'), ('5', '2');
    INSERT INTO  conduit  (id_user ,id_vehicule)
    VALUES ('5',  '1'), ('5', '2'), ('5', '3');
    -- Pas d'association avec la table deteste
    J'ai essayé ma requête qui va bien :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
     
    SELECT u.nom_user, GROUP_CONCAT(DISTINCT c.nom_couleur), GROUP_CONCAT(DISTINCT v.nom_vehicule), GROUP_CONCAT(DISTINCT f.nom_fromage)
    FROM user u
    INNER JOIN aime a ON a.id_user = u.id
    INNER JOIN conduit k ON k.id_user = u.id
    INNER JOIN deteste d ON d.id_user = u.id
    INNER JOIN couleur c ON c.id = a.id_couleur
    INNER JOIN vehicule v ON v.id = k.id_vehicule
    INNER JOIN fromage f ON f.id = d.id_fromage
    GROUP BY u.nom_user
    qui me renvoi que les 4 premiers résultats ... Albert à disparu car il aime le fromage ???

    Trêve de plaisanterie ... Je ne vois pas pourquoi il ne me colle pas albert dans les résultats avec un joli NULL dans la colonne GROUP_CONCAT(DISTINCT f.nom_fromage)

    J'ai essayer avec un where u.id=5 entre les inner join et le group by, c'est pareil !
    Sans le GROUP BY mais avec le WHERE j'ai albert mais les group_concat tous NULL ... je suis un peu perdu là !

    même ça ne me renvoi jamais Albert :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
     
    SELECT u.*
    FROM user u
    INNER JOIN aime a ON a.id_user = u.id
    INNER JOIN conduit k ON k.id_user = u.id
    INNER JOIN deteste d ON d.id_user = u.id
    INNER JOIN couleur c ON c.id = a.id_couleur
    INNER JOIN vehicule v ON v.id = k.id_vehicule
    INNER JOIN fromage f ON f.id = d.id_fromage
    LIMIT 0,200
    ????

  15. #15
    Modérateur

    Avatar de CinePhil
    Homme Profil pro
    Ingénieur d'études en informatique
    Inscrit en
    Août 2006
    Messages
    16 799
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 60
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Ingénieur d'études en informatique
    Secteur : Enseignement

    Informations forums :
    Inscription : Août 2006
    Messages : 16 799
    Points : 34 031
    Points
    34 031
    Billets dans le blog
    14
    Par défaut
    Alors il faut des jointures externes :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    SELECT u.nom_user, GROUP_CONCAT(DISTINCT c.nom_couleur), GROUP_CONCAT(DISTINCT v.nom_vehicule), GROUP_CONCAT(DISTINCT f.nom_fromage)
    FROM user u
    LEFT JOIN aime a ON a.id_user = u.id
    LEFT JOIN conduit k ON k.id_user = u.id
    LEFT JOIN deteste d ON d.id_user = u.id
    LEFT JOIN couleur c ON c.id = a.id_couleur
    LEFT JOIN vehicule v ON v.id = k.id_vehicule
    LEFT JOIN fromage f ON f.id = d.id_fromage
    GROUP BY u.nom_user
    Philippe Leménager. Ingénieur d'étude à l'École Nationale Supérieure de Formation de l'Enseignement Agricole. Autoentrepreneur.
    Mon ancien blog sur la conception des BDD, le langage SQL, le PHP... et mon nouveau blog sur les mêmes sujets.
    « Ce que l'on conçoit bien s'énonce clairement, et les mots pour le dire arrivent aisément ». (Nicolas Boileau)
    À la maison comme au bureau, j'utilise la suite Linux Mageïa !

  16. #16
    Candidat au Club
    Profil pro
    Inscrit en
    Juillet 2010
    Messages
    11
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juillet 2010
    Messages : 11
    Points : 4
    Points
    4
    Par défaut
    YES .... thank you

    Je vais de ce pas chercher la différence entre jointure externe et jointure avec INNER JOIN ...

    Merci

  17. #17
    Candidat au Club
    Profil pro
    Inscrit en
    Juillet 2010
    Messages
    11
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juillet 2010
    Messages : 11
    Points : 4
    Points
    4
    Par défaut
    Le SQL ça rulez !!!! Oh boudiouuuuuuu c'est juste trop puissant .... Merci du coup de main : j'ai fini mon projet, c'est sûrement pas terrible au point de vue programmation mais c'est fonctionnel !!!

    D'ailleurs si je poste mon projet quelque part (où d'ailleurs ?) je pourrais avoir des commentaires sur le projet ?

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

Discussions similaires

  1. Requête HQL avec tables associatives
    Par mecha31 dans le forum Hibernate
    Réponses: 1
    Dernier message: 15/05/2015, 13h32
  2. [MySQL] Requête MySQL avec table assoc
    Par GuillaumeJ28 dans le forum PHP & Base de données
    Réponses: 6
    Dernier message: 14/10/2013, 07h31
  3. [HIBERNATE] requete avec table d'association
    Par zybay dans le forum Hibernate
    Réponses: 1
    Dernier message: 14/06/2007, 12h59
  4. [MySQL] requête mysql avec condition à élaborer à partir d'un tableau
    Par taffMan dans le forum PHP & Base de données
    Réponses: 9
    Dernier message: 13/06/2007, 09h18
  5. Problème de requête MYSQL avec plusieurs limit
    Par Super_baloo8 dans le forum Requêtes
    Réponses: 1
    Dernier message: 07/05/2007, 18h35

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