[RESOLU] Sous requête possible en une seule ?

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 : [RESOLU] Sous requête possible en une seule ?

Re: Sous requête possible en une seule ?

par Zahnzao » 09 août 2012, 15:40

Ok merci beaucoup !

Résolu :)

Re: Sous requête possible en une seule ?

par Mazarini » 09 août 2012, 14:00

oops, SQL_CALC_FOUND_ROWS est mieux.

J'ai lu la question hier soir et c'est seulement ce matin que j'ai regardé la doc MySQL. J'aurai du relire la question avant de répondre. C'est une option que je vais utiliser à l'avenir.

Le gain de temps se fait sur la sélection des lignes qui n'est fait qu'une seule fois au lieu de le refaire une seconde pour le count. MySQL est obligé de faire faire la requete en entier avant d'appliquer le limit.

Re: Sous requête possible en une seule ?

par Zahnzao » 09 août 2012, 11:18

Selon vous, une seconde requête avec COUNT serait elle plus optimisée que SQL_CALC_FOUND_ROWS ?
A priori oui. Plus la requête est complexe, plus ca semble efficace.
Donc tu parles du COUNT ? Excuses moi d'insister bêtement mais en lisant ta réponse j'ai plutôt l'impression que tu parles de SQL_CALC_FOUND_ROWS.

:?

Re: Sous requête possible en une seule ?

par Mazarini » 09 août 2012, 08:04

A priori oui. Plus la requête est complexe, plus ca semble efficace.

Re: Sous requête possible en une seule ?

par Zahnzao » 08 août 2012, 20:04

Effectivement les mises a jour sont largement plus rares que la lecture. Je vais suivre ton conseil.

Je te remercie.

Vu que cela concerne la même requête, j'aurai une seconde question.

Pour mon affichage par page, j’utilise actuellement la fonction SQL_CALC_FOUND_ROWS pour compter le total des posts dans la bdd.
$queryPosts="SELECT SQL_CALC_FOUND_ROWS p.id,p.thumb,p.width,p.height,p.type
FROM posts AS p
JOIN posts_has_tags AS pt ON p.id = pt.id_post
WHERE pt.tag IN(".$tags.")
GROUP BY p.id HAVING COUNT(pt.tag) = ".$count."
ORDER BY p.id DESC
LIMIT ".$start.",20";
$queryPosts=mysql_query($queryPosts);
$totalPosts=mysql_fetch_assoc(mysql_query("SELECT FOUND_ROWS()"));
$totalPosts=$totalPosts['FOUND_ROWS()'];
Selon vous, une seconde requête avec COUNT serait elle plus optimisée que SQL_CALC_FOUND_ROWS ?

Merci.

Re: Sous requête possible en une seule ?

par Mazarini » 08 août 2012, 14:43

Dans la table des posts, tu ajoutes une colonne avec les noms des tags. Lors de l'ajout de tag ou de la suppression tu mets à jours cette colonne.

Le contenu de cette colonne sert juste à l'affichage, il dénature la structure de la base de données en mettant de la redondance d'info mais allège la lecture. La perte se fait sur la taille de la bd et sur le temps de maj. Je suppose que la lecture pour affichage des tags d'un article est fréquente contrairement aux modifications.

Re: Sous requête possible en une seule ?

par Zahnzao » 08 août 2012, 14:04

Aucun problème de performances pour l'instant puisque je suis en local, mais c'est bien pour les éviter que je pose cette question.

J'affiche 20 posts par page. Pour l'instant, l'affichage de mon contenu se fait en une seule requête. En rebouclant pour afficher les tags, je passe à 21 requêtes. D'ou ma question.

Donc je préfère ta deuxième solution mais je ne comprend pas bien ce que tu veux dire.
Avec des problèmes de performances, ajoute une chaine avec la liste des tags dans la table. Tu n'utiliseras cette liste que pour l'affichage.
Merci.

Edit: à noter que si le fait de lier l'id du tag au lieu du nom simplifierai les choses, ce n'est pas un problème, je n'ai pas beaucoup à modifier.

Re: Sous requête possible en une seule ?

par Mazarini » 08 août 2012, 13:46

Tout dépend si tu as des problèmes de performance.
Sans problèmes de performance, fais la requete de sélection et ajoute une lecture des tag par ligne lu, ou par une requete imbriquée ou par une un "in" avec la liste des id à lire.
Avec des problèmes de performances, ajoute une chaine avec la liste des tags dans la table. Tu n'utiliseras cette liste que pour l'affichage.

Re: Sous requête possible en une seule ?

par Zahnzao » 08 août 2012, 13:19

Salut, et merci pour ta réponse.

La première requête récupère les posts qui correspondent au tags envoyés par l'url (représenté ici par $tags qui est traité ailleurs dans le script)

La seconde récupère tout les tags liés à ce post (même si 3 tags sont envoyé par l'url, le post retourné peut en contenir bien plus)

Ma table tags ne sert que dans mon espace admin, elle est inutile ici car dans ma table post_has_tags je stocke le tag et non l'id. Donc post_has_tags.tag est lié à tags.name.

Et ce que je cherche à faire c'est retourner les posts liés à certains tags ($tags) fournis par l'url, mais retourner aussi les tags qui n'ont pas été soumis dans l'url pour les afficher.

Exemple:

posts (id=1)
posts (id=2)
posts (id=3)

posts_has_tags (id_post=1 ,tag='House')
posts_has_tags (id_post=1 ,tag='Cars')
posts_has_tags (id_post=2 ,tag='House')
posts_has_tags (id_post=2 ,tag='Cars')
posts_has_tags (id_post=2 ,tag='Music')
posts_has_tags (id_post=2 ,tag='Computer')
posts_has_tags (id_post=3 ,tag='House')

Donc, si j'arrive via l'url avec ?tags=House

il me retourne les 3 posts mais le post 1 contient aussi le tag 'Cars' et le posts 2 contient 3 autres tags.

avec ?tags=House+Music

il me retourne uniquement le post 2 mais je veux afficher aussi les deux autres tags lié au post 2.

Est-ce un peu plus clair ?

Re: Sous requête possible en une seule ?

par xTG » 08 août 2012, 12:49

Je ne comprends pas trop car là tu nous montres deux requêtes qui récupèrent les mêmes résultats...
Celle dans le code PHP comportant le while n'était pas plutôt en direction de la table tags ?

Auquel cas le principe est simple, il faut faire la jointure dans ce sens :
posts -> tags -> posts_has_tags
Et en lisant les résultats tu verras que pour chaque post tu auras tous les tags et les colonnes de posts_has_tags qui seront parfois null. ;)

Sous requête possible en une seule ?

par Zahnzao » 08 août 2012, 12:00

Bonjour,

je récupère des éléments dans ma base en fonction des tags qui y sont liés de manière stricte. En gros, si deux tags sont définit, il ira me chercher les élément qui possèdent obligatoirement ces deux tags et non pas l'un ou l'autre.

La requête fonctionne bien.

mes tables

tags(id,name)
posts(id,thumb,width,height,type)
posts_has_tags(id_post,tag) ces deux champs liés respectivement à posts.id et tags.name

Ma table tags n'est pas importante ici.
$tags="'cars','house','music','computer'"; // exemple de retour tags
$count= 4; // il y'a 4 tags donc $count vaut 4
// requête
$queryPosts="SELECT p.id,p.thumb,p.width,p.height,p.type
FROM posts AS p
JOIN posts_has_tags AS pt ON p.id = pt.id_post
WHERE pt.tag IN(".$tags.")
GROUP BY p.id HAVING COUNT(pt.tag) = ".$count."
ORDER BY p.id DESC"
Par contre, je veux afficher tout les tags liés à cet élément, même ceux qui ne sont pas dans $tags.

J'y arrive bien entendu en faisant une seconde requête dans ma boucle d'affichage mais je me demandait s'il était possible de le faire directement dans celle ci.
while($data=mysql_fetch_assoc($queryPosts)){
      $id=$data['id'];
      $queryTags="SELECT tag FROM posts_has_tags WHERE id_post=$id ORDER BY tag ASC";
      while(....)
          // affichage des tags
      }
}
Avez vous une idée ou une piste vers une commande sql qui pourrait m'aider ?

Merci.