Précédent   Forum du club des développeurs et IT Pro > Bases de données > MySQL
MySQL Forum d'entraide MySQL. Avant de poster -> FAQ MySQL, Tutoriels MySQL
Partagez cette discussion sur d'autres réseaux sociaux : Viadeo Twitter Google Facebook Digg Delicious MySpace Yahoo
Réponse
 
Outils de la discussion
Publicité
'
Vieux 10/12/2012, 09h32   #1
louk007
Invité de passage
 
Inscription : juillet 2010
Messages : 11
Détails du profil
Informations forums :
Inscription : juillet 2010
Messages : 11
Points : 1
Points : 1
Par défaut Requête mysql avec tables d'associations (Cas d'école ??!!)

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 :
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 :
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 :
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 :
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 :
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 :
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
louk007 est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 10/12/2012, 11h45   #2
CinePhil
Modérateur
 
Avatar de CinePhil
 
Homme Philippe Leménager
Ingénieur d'études en informatique
Inscription : août 2006
Messages : 13 659
Détails du profil
Informations personnelles :
Nom : Homme Philippe Leménager
Âge : 49
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 : 13 659
Points : 25 562
Points : 25 562
Envoyer un message via MSN à CinePhil
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 :
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 de Formation Agronomique. Autoentrepreneur.
Mon blog sur la conception des BDD, le langage SQL, le PHP avec Zend Framework...
« 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 !
CinePhil est actuellement connecté   Envoyer un message privé Réponse avec citation 00
Vieux 10/12/2012, 20h05   #3
Fred_34
Membre expérimenté
 
Homme Frédéric
Inscription : juin 2011
Messages : 442
Détails du profil
Informations personnelles :
Nom : Homme Frédéric
Localisation : France

Informations forums :
Inscription : juin 2011
Messages : 442
Points : 576
Points : 576
Ce n'est pas la meilleure façon de faire (C'est juste pour te montrer le principe du GROUP_CONCAT ) :
Code :
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
Fred_34 est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 10/12/2012, 20h34   #4
louk007
Invité de passage
 
Inscription : juillet 2010
Messages : 11
Détails du profil
Informations forums :
Inscription : juillet 2010
Messages : 11
Points : 1
Points : 1
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 !
louk007 est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 11/12/2012, 23h27   #5
Master-NiKo
Membre confirmé
 
Avatar de Master-NiKo
 
Homme
Webmaster
Inscription : juin 2005
Messages : 137
Détails du profil
Informations personnelles :
Sexe : Homme
Âge : 30
Localisation : France

Informations professionnelles :
Activité : Webmaster
Secteur : High Tech - Multimédia et Internet

Informations forums :
Inscription : juin 2005
Messages : 137
Points : 274
Points : 274
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.
Master-NiKo est actuellement connecté   Envoyer un message privé Réponse avec citation 00
Vieux 12/12/2012, 21h08   #6
louk007
Invité de passage
 
Inscription : juillet 2010
Messages : 11
Détails du profil
Informations forums :
Inscription : juillet 2010
Messages : 11
Points : 1
Points : 1
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 :
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 :
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 :
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 :
Citation:
Cent fois sur le métier remets ton ouvrage.
Meeeeeeeeeeeeeeerci
louk007 est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 12/12/2012, 21h12   #7
louk007
Invité de passage
 
Inscription : juillet 2010
Messages : 11
Détails du profil
Informations forums :
Inscription : juillet 2010
Messages : 11
Points : 1
Points : 1
Au fait ce GROUP_CONCAT c'est du SQL standard ou c'est spécifique MySQL ?
louk007 est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 12/12/2012, 21h13   #8
CinePhil
Modérateur
 
Avatar de CinePhil
 
Homme Philippe Leménager
Ingénieur d'études en informatique
Inscription : août 2006
Messages : 13 659
Détails du profil
Informations personnelles :
Nom : Homme Philippe Leménager
Âge : 49
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 : 13 659
Points : 25 562
Points : 25 562
Envoyer un message via MSN à CinePhil
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 de Formation Agronomique. Autoentrepreneur.
Mon blog sur la conception des BDD, le langage SQL, le PHP avec Zend Framework...
« 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 !
CinePhil est actuellement connecté   Envoyer un message privé Réponse avec citation 00
Vieux 12/12/2012, 21h15   #9
louk007
Invité de passage
 
Inscription : juillet 2010
Messages : 11
Détails du profil
Informations forums :
Inscription : juillet 2010
Messages : 11
Points : 1
Points : 1
Spécifique MySQL ?!! et les autres sql (NoSQL, PostgreSQL, SQL-Server), ils font comment ?
louk007 est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 12/12/2012, 21h21   #10
louk007
Invité de passage
 
Inscription : juillet 2010
Messages : 11
Détails du profil
Informations forums :
Inscription : juillet 2010
Messages : 11
Points : 1
Points : 1
Oh le bor....del !


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

Je retire ma question
louk007 est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 12/12/2012, 21h28   #11
CinePhil
Modérateur
 
Avatar de CinePhil
 
Homme Philippe Leménager
Ingénieur d'études en informatique
Inscription : août 2006
Messages : 13 659
Détails du profil
Informations personnelles :
Nom : Homme Philippe Leménager
Âge : 49
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 : 13 659
Points : 25 562
Points : 25 562
Envoyer un message via MSN à CinePhil
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 de Formation Agronomique. Autoentrepreneur.
Mon blog sur la conception des BDD, le langage SQL, le PHP avec Zend Framework...
« 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 !
CinePhil est actuellement connecté   Envoyer un message privé Réponse avec citation 00
Vieux 13/12/2012, 06h49   #12
louk007
Invité de passage
 
Inscription : juillet 2010
Messages : 11
Détails du profil
Informations forums :
Inscription : juillet 2010
Messages : 11
Points : 1
Points : 1
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)
louk007 est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 15/12/2012, 08h06   #13
louk007
Invité de passage
 
Inscription : juillet 2010
Messages : 11
Détails du profil
Informations forums :
Inscription : juillet 2010
Messages : 11
Points : 1
Points : 1
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 ?
louk007 est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 15/12/2012, 08h53   #14
louk007
Invité de passage
 
Inscription : juillet 2010
Messages : 11
Détails du profil
Informations forums :
Inscription : juillet 2010
Messages : 11
Points : 1
Points : 1
Requête pour ajouter Albert (id=5):
Code :
1
2
3
 
INSERT INTO  user (nom_user)
VALUES ('Albert');
requêtes pour ajouter l'entrée dans les tables d'associations :
Code :
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 :
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 :
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
????
louk007 est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 15/12/2012, 11h15   #15
CinePhil
Modérateur
 
Avatar de CinePhil
 
Homme Philippe Leménager
Ingénieur d'études en informatique
Inscription : août 2006
Messages : 13 659
Détails du profil
Informations personnelles :
Nom : Homme Philippe Leménager
Âge : 49
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 : 13 659
Points : 25 562
Points : 25 562
Envoyer un message via MSN à CinePhil
Alors il faut des jointures externes :
Code :
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 de Formation Agronomique. Autoentrepreneur.
Mon blog sur la conception des BDD, le langage SQL, le PHP avec Zend Framework...
« 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 !
CinePhil est actuellement connecté   Envoyer un message privé Réponse avec citation 00
Vieux 15/12/2012, 11h23   #16
louk007
Invité de passage
 
Inscription : juillet 2010
Messages : 11
Détails du profil
Informations forums :
Inscription : juillet 2010
Messages : 11
Points : 1
Points : 1
YES .... thank you

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

Merci
louk007 est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 30/12/2012, 09h04   #17
louk007
Invité de passage
 
Inscription : juillet 2010
Messages : 11
Détails du profil
Informations forums :
Inscription : juillet 2010
Messages : 11
Points : 1
Points : 1
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 ?
louk007 est déconnecté   Envoyer un message privé Réponse avec citation 00
Réponse Cette discussion est résolue.
Outils de la discussion

Navigation rapide


Fuseau horaire GMT +2. Il est actuellement 19h48.


 
 
 
 
Partenaires

Hébergement Web