problème de requête

VaN
Mammouth du PHP | 1107 Messages

16 janv. 2008, 18:07

Bonjour,

je possède deux tables, USERS et CONCOURS. Dans la table CONCOURS, j'enregistre entre autre le user_id de la personne qui a proposé le concours à la base de données.

Je souhaite ensuite afficher la liste de mes USERS, avec leur login, mail, etc, et également le nombre de concours qu'ils ont proposés. Le problème est que ma requête, telle qu'elle est conçue, ne me sort que les USERS qui ont proposés des concours, pas les autres.

La requête en question :
$sql = 	"SELECT user_id, user_login, user_level, user_mail, COUNT(concours_id) as concours
		FROM ".$prefixe."users, ".$prefixe."concours
		WHERE concours_user_id = user_id
		GROUP BY user_id";
les structures des tables USERS et CONCOURS :
CREATE TABLE `users` (
`user_id` int(11) NOT NULL auto_increment,
`user_login` text character set latin1 collate latin1_general_cs NOT NULL,
`user_pass` text character set latin1 collate latin1_general_cs NOT NULL,
`user_mail` text NOT NULL,
`user_level` tinyint(4) NOT NULL,
`user_activated` tinyint(4) NOT NULL,
`user_activation_key` text character set latin1 collate latin1_general_cs NOT NULL,
PRIMARY KEY (`user_id`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1 AUTO_INCREMENT=19 ;
CREATE TABLE `concours` (
`concours_id` int(11) NOT NULL auto_increment,
`concours_user_id` int(11) NOT NULL,
`concours_site_id` int(11) NOT NULL,
`concours_url` text NOT NULL,
`concours_start_date` datetime NOT NULL,
`concours_end_date` datetime NOT NULL,
`concours_type` tinyint(4) NOT NULL,
`concours_qs` enum('Oui','Non') NOT NULL,
`concours_nb_reponses` tinyint(4) NOT NULL,
`concours_reponses` text NOT NULL,
`concours_lots` text NOT NULL,
`concours_comments` text NOT NULL,
`concours_rating` tinyint(4) NOT NULL,
`concours_activated` tinyint(4) NOT NULL,
PRIMARY KEY (`concours_id`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1 AUTO_INCREMENT=8 ;

Existe-il un moyen de sortir également les USERS n'ayant pas proposé de concours, en une seule requête, ou dois-je faire 2 requêtes disctinctes, une pour sortir tous les USERS, et une autre pour compter le nombre de concours proposés ?

Avatar du membre
Modérateur PHPfrance
Modérateur PHPfrance | 10684 Messages

16 janv. 2008, 18:11

Il te faut pour cela utiliser une jointure externe afin que les enregistrements qui n'ont pas de correspondance dans l'autre table soit tout de même restituer (avec une valeur null pour le nombre de concours)

Regarde du côté des INNER JOIN / OUTER JOIN dans la documentation :)
Ce n'est pas en améliorant la bougie que l'on a inventé l'ampoule...

VaN
Mammouth du PHP | 1107 Messages

16 janv. 2008, 18:37

Ouh la, ça a l'air bien compliqué, et c'est quelque chose que je n'ai jamais utilisé : /

j'ai tenté un
$sql = 	"SELECT user_id, user_login, user_level, user_mail, COUNT(concours_id) as concoursProposes
		FROM ".$prefixe."users
		INNER JOIN ".$prefixe."concours ON user_id = concours_user_id
		WHERE concours_user_id IS NULL
		GROUP BY user_id";
après m'être inspiré de la doc, et de plusieurs exemples sur le web, mais evidemment ça ne marche pas. Ma requête ne me sort aucun résultat.

Par contre, si je remplace le INNER JOIN par un LEFT JOIN (que je n'ai jamais utilisé non plus avant, mais dont j'avais deja entendu parlé), la requête me renvoie les USERS qui n'ont pas proposés de concours.

Eléphant du PHP | 175 Messages

17 janv. 2008, 11:03

le left join te renvoi une ligne pour chaque enrgistrement correspondant la clause ON (le left join te renvoit quand meme les enregistrement lies au from)

Le inner join fait la meme chose mais est une jointure totale entre les tables (equivalent d'un from users, concours)

http://dev.mysql.com/doc/refman/5.0/fr/join.html

donc plutot comme ca ;)
$sql =     "SELECT user_id, user_login, user_level, user_mail, COUNT(concours_id) as concoursProposes 
FROM ".$prefixe."users 
LEFT JOIN ".$prefixe."concours ON user_id = concours_user_id 
GROUP BY user_id";

ViPHP
ViPHP | 4039 Messages

17 janv. 2008, 12:40

Celle de steph fonctionne, et celle-ci aussi:

Code : Tout sélectionner

SELECT u.user_id as user_id,u.user_login as user_login, u.user_level as user_level, u.user_mail as user_mail, (coalesce c.count,0) as concours FROM users AS u LEFT JOIN (SELECT concours_user_id as user_id, count(*) as count FROM concours GROUP BY concours_user_id) as c ON (u.user_id = c.user_id)


qui devrait retourner un résultat comme ceci:

Code : Tout sélectionner

user_id user_login user_level user_mail concours ------- ---------- ---------- --------- -------- 124 12 8 jose@fr 45
voilà voilà :wink:
Mais qu'importe. (je suis ici - dernier petit projet)
Berze going social.

VaN
Mammouth du PHP | 1107 Messages

17 janv. 2008, 16:37

Effectivement, celle de steph29 fonctionne très bien : )

Merci, je vais potasser un peu ces systemes de jointure, qui ont l'air assez puissants.