Select et limit en jointure

Répondre


Cette question est un moyen d’empêcher des soumissions automatisées de formulaires par des robots.
Smileys
:D :) :( :o :shock: :? 8-) :lol: :x :P :oops: :cry: :evil: :twisted: :roll: :wink: :!: :?: :idea: :arrow: :| :mrgreen: =D> #-o =P~ :^o :non: :priere: 8-|
Voir plus de smileys
  Revue du sujet
 

  Étendre la vue Revue du sujet : Select et limit en jointure

par nelumbo » 23 juin 2008, 22:28

Je prends note :) . J'avais d'ailleurs lu dans un bouquin qu'il faut être le plus précis possible lors de la construction d'une requête.

par Rei Itchido » 23 juin 2008, 19:01

Sans regarder ta requête précisément, utiliser * est à proscrire. Préfère toujours énumérer les seuls champs dont tu as besoin.

par Shrell » 23 juin 2008, 18:34

normal, en faisant un DISTINCT *, il faut que l'intégralité des champs soient égaux si tu veux que les lignes soient fusionnées. Donc n'importe quelle valeurs DISTINCTE (le nom de la photo par exemple) te retourne plusieurs lignes :wink:

par nelumbo » 23 juin 2008, 18:04

Ca fonctionne :D

Un grand merci à tout le monde. Voilà ce qui fonctionne sur mon serveur:
 	if (isset($_GET["pic_only"]))
 		$sql = "SELECT DISTINCT username, f_13, f_2, f_12, f_1 FROM users LEFT JOIN picture ON picture.profile=users.username WHERE (";
 	else 
 		$sql = "SELECT * from users where (";
J'ai du remplacer * par username, f_13, f_2, f_12, f_1 . Bizzarement, le * affiche des doublons et donc fausse les résultats. Va comprendre :shock: .

par Shrell » 23 juin 2008, 14:02

if (isset($_GET["pic_only"])) 
         $sql = "SELECT * from users,picture where ("; 
     else  
         $sql = "SELECT * from users where (";
Je sais je radote :oops: mais tu fais un produit cartésien de tes deux tables, tu vas écrouler ton serveur
pars sur :
if (isset($_GET["pic_only"])) 
         $sql = "SELECT * from users LEFT JOIN picture ON users.id=picture.profile where ( "; 
     else  
         $sql = "SELECT * from users where (";
Et dans ce cas là, étant donné que tu vas rajouter un "AND picture.main=1 AND picture.validated=1", le "IS NOT NULL" est implicite, tu n'en as donc plus besoin

Et comme le fait remarquer Rei Itchido, ne pas oublier le distinct ;)

par Rei Itchido » 23 juin 2008, 13:48

Et le DISTINCT?

par nelumbo » 23 juin 2008, 13:23

Code : Tout sélectionner

SELECT DISTINCT username FROM users LEFT JOIN picture ON picture.profile=users.username WHERE picture.id IS NOT NULL
Le nombre d'username semble correspondre (fichier test). Mais, il y'a un hic. Lorsque j'intègre la requête à mon script j'ai des 'username' en doublon... Autant d'username affiché que d'entrées dans picture.
if (getParam("pic_only",""))
{
	if ($set_validate_on)
		$addOnSQL.=" AND picture.profile=users.username AND picture.main=1 AND picture.validated=1";
	else 
		$addOnSQL.=" AND picture.profile=users.username AND picture.main=1";
	
	$addOnSQL.=$sql;
	$addOnParams.="&pic_only=1&";		
}
dans mon fichier de fonctions:
 	if (isset($_GET["pic_only"]))
 		$sql = "SELECT * from users,picture where (";
 	else 
 		$sql = "SELECT * from users where (";
En fait, pour faire simple, il faudrait que je change uniquement la fin de la requête.

Nota: validate est sur on

par steph29 » 23 juin 2008, 12:24

Avec l'utilisation de LEFT JOIN on n'est pas sensé récupérer uniquement les lignes qui ont une correspondance justement? :-k
Sans le WHERE IS NOT NULL j'entends
Non justement, c'est l'interet du left join ;)
S'il y a une ligne dans A qui répond à la clause WHERE, mais qu'il n'y avait aucune ligne dans B qui répondait à la condition du LEFT JOIN, alors une ligne supplémentaire de B est générée avec toutes les colonnes mises à NULL.
src: http://dev.mysql.com/doc/refman/5.0/fr/ ... ation.html

par Shrell » 23 juin 2008, 12:05

j'aurais dit pareil... maintenant j'ai répondu avec la tête dans le ***
Donc je ne vois vraiment pas ce qui cloche :-k

par Rei Itchido » 23 juin 2008, 10:16

Avec l'utilisation de LEFT JOIN on n'est pas sensé récupérer uniquement les lignes qui ont une correspondance justement? :-k
Sans le WHERE IS NOT NULL j'entends

par Shrell » 23 juin 2008, 10:01

Dans ce cas :

Code : Tout sélectionner

SELECT DISTINCT username FROM users LEFT JOIN picture ON picture.profile=users.username WHERE picture.id IS NOT NULL

par nelumbo » 22 juin 2008, 20:38

Code : Tout sélectionner

SELECT DISTINCT username FROM users LEFT JOIN picture ON picture.profile=users.username
Cela sélectionne tous les 'username'. Je souhaite uniquement ceux qui ont une photo :) .

par Shrell » 22 juin 2008, 19:13

Code : Tout sélectionner

SELECT users.username FROM users, picture WHERE picture.profile=users.username
à première vue je vois deux problèmes dans ce code : d'abord je mettrais les conditions de jointure dans le "ON" et pas dans le "WHERE", mais ça...
ensuite, si un user a posté plusieurs photos, il va ressortir plusieurs fois
donc je dirais :

Code : Tout sélectionner

SELECT DISTINCT username FROM users LEFT JOIN picture ON picture.profile=users.username

par nelumbo » 22 juin 2008, 15:47

Ca ne fonctionne pas.

Voici la requête, ou plutôt une partie car celle ci est découpée en plusieurs options de recherche. Pas facile de s'y retrouver.

Code : Tout sélectionner

SELECT * from users,picture where picture.profile=users.username AND picture.main=1 AND picture.validated=1
La table users

Code : Tout sélectionner

CREATE TABLE `users` ( `username` varchar(70) NOT NULL default '', `email` varchar(255) default NULL, `password` varchar(70) default NULL, `ipaddress` varchar(30) default NULL, `joined` int(11) default '0', `lastlogin` int(11) default NULL, `expire_date` int(11) default NULL, `completed_profile` int(11) default '0', `pay_upload` smallint(6) default '0', `pay_contact` smallint(6) default '0', `pay_webchat` smallint(6) default '0', `pay_gb` smallint(6) default '0', `pay_rotate` smallint(6) default '0', `pay_visitor` smallint(6) default '0', `pay_fav` smallint(6) default '0', `pay_match` smallint(6) default '0', `pay_flirts` smallint(6) default '0', `delete_me` int(11) default '0', `f_1` smallint(6) default NULL, `f_2` varchar(255) default NULL, `f_4` smallint(6) default NULL, `f_3` smallint(6) default NULL, `f_5` smallint(6) default NULL, `lookingf_1` smallint(6) default NULL, `lookingf_3` smallint(6) default NULL, `f_6` smallint(6) default NULL, `lookingf_6` varchar(255) default NULL, `betweenFromf_6` varchar(255) default NULL, `betweenTof_6` varchar(255) default NULL, `lookingf_2` varchar(255) default NULL, `betweenFromf_2` varchar(255) default NULL, `betweenTof_2` varchar(255) default NULL, `f_7` smallint(6) default NULL, `f_8` smallint(6) default NULL, `f_9` smallint(6) default NULL, `f_10` varchar(255) default NULL, `f_11` varchar(255) default NULL, `f_12` smallint(6) default NULL, `lookingf_12` varchar(255) default NULL, `f_13` text, `f_14` varchar(255) default NULL, `f_15` smallint(6) default NULL, `f_16` smallint(6) default NULL, `f_17` varchar(255) default NULL, `f_18` text, `visits` int(11) default '0', `validated` int(11) default NULL, `video` varchar(190) default NULL, `notify_flirts` smallint(6) default '1', `notify_localmsg` smallint(6) default '2', `notify_important` tinyint(4) default '2', `f_23` smallint(6) default NULL, `lookingf_23` smallint(6) default NULL, `f_25` smallint(6) default NULL, `lookingf_25` smallint(6) default NULL, `betweenFromf_3` smallint(6) default NULL, `betweenTof_3` smallint(6) default NULL, `betweenFromf_23` smallint(6) default NULL, `betweenTof_23` smallint(6) default NULL, PRIMARY KEY (`username`) ) ENGINE=MyISAM DEFAULT CHARSET=utf8;
La table picture:

Code : Tout sélectionner

CREATE TABLE `picture` ( `id` int(4) NOT NULL auto_increment, `profile` varchar(50) default NULL, `filename` varchar(50) default NULL, `filesize` varchar(50) default NULL, `filetype` varchar(50) default NULL, `imagew` varchar(10) default NULL, `imageh` varchar(10) default NULL, `main` int(1) default '0', `validated` int(1) default '0', `descr` varchar(255) default NULL, `points` int(11) default '0', `voters` int(11) default '0', `grade` double(3,2) default NULL, PRIMARY KEY (`id`) ) ENGINE=MyISAM AUTO_INCREMENT=707 DEFAULT CHARSET=utf8 AUTO_INCREMENT=707 ;

par Ryle » 22 juin 2008, 12:22

La commande GROUP BY sert lorsque l'on utilise des fonctions regroupant les résultats de plusieurs enregistrements (comme SUM, AVG, ...) pour lier les colonnes qui n'ont pas été groupées, donc à priori rien à voir ici.

Le LIMIT n'aura pas plus d'effet ici, puisque celui-ci se contente de limiter le nombre d'enregistrement retournés par la requête, mais n'affecte en rien les résultats de celle-ci.

Normalement dans ton cas, une simple jointure entre tes deux tables doit suffir, et un

Code : Tout sélectionner

SELECT users.username FROM users, picture WHERE picture.profile=users.username
devrait déjà ne te retourner que les username pour lesquels une correspondance a été trouvée dans la table picture.

Si tel n'est pas le cas, donne nous la structure des deux tables (les create table) et la requête complète...