Requete simultanee sur 2 tables

Requete simultanee sur 2 tables - PHP - Programmation

Marsh Posté le 20-02-2008 à 09:37:11    

Bonjour,
 
je me sert pas souvent de mysql mais j'ai besoin de faire une requête que je n'arrive pas à écrire, malgrés mes recherches
 
J'ai une table annonce
J'ai une table img qui a une relation avec les annonces (parent)
 
Mon but c'est de faire une requete qui sort des annonces avec par ordre de priorité que le champs star de la table avec annonce soit à 6 au lieu de 0 et aussi en aleatoire ce que j'ai reussit a faire:
 
  $query_annonce="SELECT * FROM annonce WHERE actif='1' and cat='".enr_data($cat)."' ORDER BY star desc,rand($date_aleatoire)";
 
Maintenant je souhaiterai ajouter en second critère pour l'ordre que si l'annonce a une photo enregistré dans la table img, elle soit prioritaire
 
Voila mon bout de code, mais je ne sait pas par ou finir, si vous pouviez m'aider, merci
 
 
$query_annonce="SELECT * FROM annonce INNER JOIN img Where annonce.actif='1' and annonce.cat='".enr_data($cat)."' ORDER BY annonce.star,img.parent desc,rand($date_aleatoire)";

Reply

Marsh Posté le 20-02-2008 à 09:37:11   

Reply

Marsh Posté le 20-02-2008 à 10:06:27    

Déjà il ta faut une jointure externe, sinon tu vas perdre toutes les annonces sans image.
Et ensuite il suffit de faire un order by ton_champ_photo, a priori les valeurs nulles seront à la fin


---------------
Can't buy what I want because it's free -
Reply

Marsh Posté le 20-02-2008 à 10:16:49    

manque le ON de la jointure aussi


---------------
Software and cathedrals are much the same - first we build them, then we pray.
Reply

Marsh Posté le 20-02-2008 à 10:18:26    

anapajari a écrit :

manque le ON de la jointure aussi


ça dépend, ça. Si la clé d'une des tables est déclarée clé étrangère dans l'autre ça peut être implicite (enfin avec un natural join, pour moi, mais pourquoi pas sur un inner, j'en sais rien [:petrus75]).


---------------
Can't buy what I want because it's free -
Reply

Marsh Posté le 20-02-2008 à 10:22:58    

skeye a écrit :


ça dépend, ça. Si la clé d'une des tables est déclarée clé étrangère dans l'autre ça peut être implicite (enfin avec un natural join, pour moi, mais pourquoi pas sur un inner, j'en sais rien [:petrus75]).


ça condition elle est dans le where la:

Code :
  1. and annonce.cat='".enr_data($cat)."'

:o
edit: ah non je dit des conneries
edit2: From the doc:

Citation :

Notez que dans les versions antérieures à la 3.23.17, INNER JOIN ne prenait pas en compte condition_jointure !


et également:

Citation :

INNER JOIN et ,  (virgule) sont sémantiquement équivalents. Les deux opèrent une jointure totale sur les tables utilisées. Normalement, vous spécifiez les conditions de jointure dans la clause WHERE


Et là moi je dis beurk


Message édité par anapajari le 20-02-2008 à 10:27:59

---------------
Software and cathedrals are much the same - first we build them, then we pray.
Reply

Marsh Posté le 20-02-2008 à 10:33:07    

Déja merci pour vos réponses, j'ai essayer une jointure externe:
 
  $query_annonce="SELECT * FROM annonce LEFT JOIN img ON (annonce.id=img.annonce) WHERE annonce.actif='1' and  
 
annonce.cat='".enr_data($cat)."'";
 
à noter que la correspondance entre les tables sont id pour table annonce et annonce pour table img (contrairement a ce que j'ai dit)
 
Cette requete marche mais me sort des doublons (s'il y a 3 photos par ex il me sortira 3 fois l'annonce en plus des autres)
Et quand je met a la fin order by img (pour faire le tri si image ou pas) la ca me fait une erreur

Reply

Marsh Posté le 20-02-2008 à 10:45:58    

Ah ben oui s'il y a 3 photos ça va te sortir les 3 en effet. Mot clé distinct.[:dawa]
 
Ca te sort  quoi comme erreur?


---------------
Can't buy what I want because it's free -
Reply

Marsh Posté le 20-02-2008 à 10:54:32    

probablement qu'img est un nom de table, pas un nom de champs. Le tout a la sauce imbitable mysql, le seul sgbd case sensitive.

Reply

Marsh Posté le 20-02-2008 à 10:55:42    

si je met distinct comme ca ca ne marche pas:
 
$query_annonce="SELECT distinct FROM annonce LEFT JOIN img ON (annonce.id=img.annonce) WHERE annonce.actif='1' and  
 
annonce.cat='".enr_data($cat)."'";  
 
sinon quand ca me sort des erreurs:
 
Warning: mysql_num_rows(): supplied argument is not a valid MySQL result resource in

Reply

Marsh Posté le 20-02-2008 à 10:56:35    

bugbug2 a écrit :

si je met distinct comme ca ca ne marche pas:
 
$query_annonce="SELECT distinct FROM annonce LEFT JOIN img ON (annonce.id=img.annonce) WHERE annonce.actif='1' and  
 
annonce.cat='".enr_data($cat)."'";  
 
sinon quand ca me sort des erreurs:
 
Warning: mysql_num_rows(): supplied argument is not a valid MySQL result resource in


sans déconner? [:el g]
ça te dirait pas de tester avec une requête correcte?


---------------
Can't buy what I want because it's free -
Reply

Marsh Posté le 20-02-2008 à 10:56:35   

Reply

Marsh Posté le 20-02-2008 à 10:57:12    

oui img est bien un nom de table

Reply

Marsh Posté le 20-02-2008 à 10:58:14    

bugbug2 a écrit :

oui img est bien un nom de table


...et tu fais order by img? T'as la moindre notion de sql ou tu tapes des trucs au pif en espérant que ça va marcher?


---------------
Can't buy what I want because it's free -
Reply

Marsh Posté le 20-02-2008 à 11:01:42    

Oui je suis entièrement novice, c'est pour ca que je vous demande votre aide. Merci

Reply

Marsh Posté le 20-02-2008 à 11:03:14    

Bon, alors commence par apprendre les bases. Trouve-toi un cours de base sur sql et apprends comment ça fonctionne, au lieu de tâtonner.


Message édité par skeye le 20-02-2008 à 11:03:19

---------------
Can't buy what I want because it's free -
Reply

Marsh Posté le 20-02-2008 à 11:06:24    

On se calme, on est pas la pour jeter tout ceux qui n'ont pas la reponse a leur probleme...
Le plus simple est de garder ta requete initiale et de rajouter un critere qui vaut 1 si ton image est presente et 0 si elle ne l'est pas et de trier selon ce truc, je fais 1 ou 2 essais et je te poste qq chose a adapter dans qq minutes.

Reply

Marsh Posté le 20-02-2008 à 11:10:39    

ok, merci

Reply

Marsh Posté le 20-02-2008 à 11:14:15    

voila, a adapter, j'affiche d'abord les utilisateurs qui ont un lien existant dans stx_client. Comme je veux pas te filer un truc qui marche pas, tu as un peu de taf simple :

Code :
  1. select *,
  2. case exists(select null from stx_client where stx_client.client_utilisateur = utilisateur.pk_utilisateur) when true then 1 else 0 end as tri
  3. from utilisateur
  4. order by tri asc


La colonne tri vaut 1 quand la condition exists est verifiee, donc les enregistrements avec un truc dans stx_client qui verifient la jointure sont affiches en premiers.

Reply

Marsh Posté le 20-02-2008 à 11:28:27    

fred777888999 a écrit :

On se calme, on est pas la pour jeter tout ceux qui n'ont pas la reponse a leur probleme...


Non, on est là pour aider les gens. Mais pas n'importe-comment. Ce n'est pas l'aider de lui donner une réponse toute faite qu'il ne comprendra pas. S'il n'a pas les bases en sql il sera bloqué de la même manière à la prochaine difficulté et devra revenir demander de l'aide.
S'il commence par lire un cours pour débutants et faire des exercices, non seulement il aura moins souvent besoin d'aide, mais il comprendra mieux nos réponses s'il a quand même des problèmes.


Message édité par skeye le 20-02-2008 à 11:28:45

---------------
Can't buy what I want because it's free -
Reply

Marsh Posté le 20-02-2008 à 11:28:57    

ok, merci beaucoups, ca marche (il y a du mal mais c bon lol)
 
$query_annonce="select *,case exists(select null from img where img.annonce = annonce.id) when true then 1 else 0 end as  
 
tri from annonce WHERE actif='1' and cat='".enr_data($cat)."' and type_annonce='".enr_data($type_annonce)."' order by star desc,tri  
 
desc,rand($date_aleatoire)";

Reply

Marsh Posté le 20-02-2008 à 11:43:22    

fred777888999 a écrit :

voila, a adapter, j'affiche d'abord les utilisateurs qui ont un lien existant dans stx_client. Comme je veux pas te filer un truc qui marche pas, tu as un peu de taf simple :

Code :
  1. select *,
  2. case exists(select null from stx_client where stx_client.client_utilisateur = utilisateur.pk_utilisateur) when true then 1 else 0 end as tri
  3. from utilisateur
  4. order by tri asc


La colonne tri vaut 1 quand la condition exists est verifiee, donc les enregistrements avec un truc dans stx_client qui verifient la jointure sont affiches en premiers.


 [:claque2000]  [:claque2000]  [:claque2000]
Et une sous-requête inutile pour la 4, une ...

Code :
  1. SELECT annonce.id, {... les autres champs annonce nécessaires ...}, count(img.annonce) AS NbPic
  2. FROM
  3. annonce
  4. LEFT JOIN img ON (annonce.id=img.annonce)
  5. WHERE annonce.actif='1' AND  annonce.cat='X'
  6. GROUP BY annonce.id, {... les autres champs annonce nécessaires ...}
  7. ORDER BY ...


Et en bonus tu as le nombre de photos de ton annonce


Message édité par anapajari le 20-02-2008 à 11:43:53

---------------
Software and cathedrals are much the same - first we build them, then we pray.
Reply

Marsh Posté le 20-02-2008 à 11:54:44    

Whaaaa, remplacement d'une sous requete avec un acces via probablement une clef primaire par un clause group by geante et une jointure. Ca c'est de l'optimisation beton comme je les aime. :ptdr:

Reply

Marsh Posté le 20-02-2008 à 12:33:50    

fred777888999 a écrit :

Whaaaa, remplacement d'une sous requete avec un acces via probablement une clef primaire par un clause group by geante et une jointure. Ca c'est de l'optimisation beton comme je les aime. :ptdr:


marre toi si tu veux, la prochaine fois tu testeras et ça t'evitera de passer pour un idiot [:spamafote]
 
A titre d'exemple, sur deux tables de 300K et 500K lignes, le cout de ta requête (sur un DB2 V9) est à 3035, celui de la mienne à 1967(pour traduire la tienne prend 62% plus de temps).
Si tu veux., je peux aussi de montrer les acces plan que tu vois bien le tablescan que tu forces avec ton exists
 
.


---------------
Software and cathedrals are much the same - first we build them, then we pray.
Reply

Marsh Posté le    

Reply

Sujets relatifs:

Leave a Replay

Make sure you enter the(*)required information where indicate.HTML code is not allowed