2010-01-19 6 views
0

J'essaie d'écrire une requête sql qui récupère tous les tags liés à chaque sujet affiché sur la page.comment puis-je afficher tous les tags liés à tous les commentaires dans une requête

comme celui-ci

 
TITLE: feedback1 
POSTED BY: User1 
CATEGORY: category1 
TAGS: tag1, tag2, tag3 

TITLE: feedback2 
POSTED BY: User2 
CATEGORY: category2 
TAGS: tag2, tag5, tag7,tag8 

TITLE: feedback3 
POSTED BY: User3 
CATEGORY: category3 
TAGS: tag1, tag5, tag6, tag3 

La relation des balises aux sujets est beaucoup à beaucoup.

En ce moment, je récupère d'abord tous les sujets de la table "topics" et récupère les balises liées de chaque sujet que je boucle sur le tableau de sujets retourné pour aller chercher des balises. Mais cette méthode est très coûteuse en termes de rapidité et pas efficace aussi.

S'il vous plaît, aidez-moi à écrire cette requête sql.

requête pour aller chercher tous les sujets et ses informations sont les suivantes:

SELECT 
    tbl_feedbacks.pk_feedbackid as feedbackId, 
    tbl_feedbacks.type as feedbackType, 
    DATE_FORMAT(tbl_feedbacks.createdon,'%M %D, %Y') as postedOn, 
    tbl_feedbacks.description as description, 
    tbl_feedbacks.upvotecount as upvotecount, 
    tbl_feedbacks.downvotecount as downvotecount, 
    (tbl_feedbacks.upvotecount)-(tbl_feedbacks.downvotecount) as totalvotecount, 
    tbl_feedbacks.viewcount as viewcount, 
    tbl_feedbacks.title as feedbackTitle, 
    tbl_users.email as userEmail, 
    tbl_users.name as postedBy, 
    tbl_categories.pk_categoryid as categoryId, 
    tbl_clients.pk_clientid as clientId 
FROM 
    tbl_feedbacks 
LEFT JOIN tbl_users 
    ON (tbl_users.pk_userid = tbl_feedbacks.fk_tbl_users_userid) 
LEFT JOIN tbl_categories 
    ON (tbl_categories.pk_categoryid = tbl_feedbacks.fk_tbl_categories_categoryid) 
LEFT JOIN tbl_clients 
    ON (tbl_clients.pk_clientid = tbl_feedbacks.fk_tbl_clients_clientid) 
WHERE 
    tbl_clients.pk_clientid = '1' 

Quelle est la meilleure pratique à suivre dans de tels cas lorsque vous devez afficher toutes les balises liées à tous les sujets en cours d'affichage sur une seule page. Comment puis-je modifier la requête sql ci-dessus, de sorte que toutes les balises et les informations connexes des sujets soient récupérées en utilisant une requête unique. Pour une démo de ce que j'essaye de réaliser est similaire à la page 'questionstions' de stackoverflow. Toutes les informations (tags + informations de chaque sujet affiché) sont correctement affichées.

Merci

+0

Où sont stockées vos étiquettes? – Wil

+0

Je stocke des balises dans une table nommée "tbl_tags". Les sujets sont stockés dans "tbl_topics" et tous les sujets liés sont récupérés en utilisant la table jointe des sujets et tags "tbl_topics_tags" –

+0

(J'ai édité ma réponse avec quelques questions de clarification qui ne rentre pas bien dans un commentaire) –

Répondre

3

Pour ce faire, je l'aurais trois tables:

Topics 
    topic_id 
    [whatever else you need to know for a topic] 
Tags 
    tag_id 
    [etc] 
Map 
    topic_id 
    tag_id 

select t.[whatever], tag.[whatever] 
    from topics t 
    join map m on t.topic_id = m.topic_id 
    join tags tag on tag.tag_id = m.tag_id 
    where [conditionals] 

Mettre en place des partitions et/ou les index sur la table de carte pour maximiser la vitesse de votre requête. Par exemple, si vous avez beaucoup plus de sujets que de balises, partitionnez la table sur les sujets. Ensuite, chaque fois que vous saisissez toutes les balises pour un sujet, il sera 1 lecture d'un domaine, aucune recherche nécessaire. Assurez-vous d'avoir indexé les sujets et les balises sur leur _id.

Utilisez votre outil «plan d'explication». (Je ne suis pas familier avec MySQL, mais je suppose qu'il ya un certain outil qui peut vous dire comment une requête sera exécutée, vous pouvez l'optimiser)

EDIT:

Vous avez les tableaux suivants:

tbl_feedbacks 
tbl_users 
tbl_categories 
tbl_clients 
tbl_tags 
tbl_topics 
tbl_topics_tags 

La requête que vous fournissez comme point de départ montre comment les commentaires, les utilisateurs, les catégories et les clients sont liés les uns aux autres.

Je suppose que tbl_topics_tags contient des FK aux étiquettes et aux rubriques, indiquant quel sujet a quelle étiquette. Est-ce correct?

Quoi de (réactions, utilisateurs, catégories et clients) a un FK à des sujets ou des balises? Ou, est-ce que les sujets ou les balises ont un FK à l'un des 4 premiers?

Une fois que je le saurai, je serai capable de montrer comment modifier la requête.

EDIT # 2

Il y a deux façons d'aller à ce sujet:

Le moyen facile est juste rejoindre sur votre FK. Cela vous donnera une ligne pour chaque tag. Il est beaucoup plus facile et plus flexible d'assembler le SQL pour le faire de cette façon. Si vous utilisez un autre langage pour prendre les résultats de la requête et les traduire pour les présenter à l'utilisateur, cette méthode est préférable. Si rien d'autre, il sera beaucoup plus évident ce qui se passe, et sera plus facile à déboguer et à maintenir. Toutefois, vous souhaiterez peut-être que chaque ligne des résultats de la requête contienne un commentaire (et les tags qui vont avec).

SQL joining question < - c'est une question que j'ai posté sur comment faire ceci. La réponse que j'ai acceptée est une réponse oracle seulement AFAIK, mais il y a d'autres réponses non-oracle.

Adaptation de la réponse de Kevin (qui est censé fonctionner dans les systèmes conformes SQL92):

select 
[other stuff: same as in your post], 
(select tag 
    from tbl_tag tt 
    join tbl_feedbacks_tags tft on tft.tag_id = tt.tag_id 
    where tft.fk_feedbackid = tbl_feedbacks.pk_feedbackid 
    order by tag_id 
    limit 1 
    offset 0) as tag1, 
(select tag 
    from tbl_tag tt 
    join tbl_feedbacks_tags tft on tft.tag_id = tt.tag_id 
    where tft.fk_feedbackid = tbl_feedbacks.pk_feedbackid 
    order by tag_id 
    limit 1 
    offset 1) as tag2, 
(select tag 
    from tbl_tag tt 
    join tbl_feedbacks_tags tft on tft.tag_id = tt.tag_id 
    where tft.fk_feedbackid = tbl_feedbacks.pk_feedbackid 
    order by tag_id 
    limit 1 
    offset 2) as tag3 
from [same as in the OP] 

Cela devrait faire l'affaire.

Notes:

Cela va tirer les trois premières balises. AFAIK, il n'y a pas moyen d'avoir un nombre arbitraire de tags. Vous pouvez augmenter le nombre de tags affichés en copiant et en collant plusieurs de ces parties de la requête. Assurez-vous d'augmenter le paramètre offset.

Si cela ne fonctionne pas, vous devrez probablement écrire une autre question, en vous concentrant sur la façon de faire le pivot dans mysql. Je n'ai jamais utilisé mysql, donc je devine seulement que cela fonctionnera en fonction de ce que les autres m'ont dit.

Un conseil: vous aurez généralement plus d'attention à votre question si vous supprimez tous les détails supplémentaires. Dans la question que j'ai liée à ci-dessus, j'étais vraiment rejoindre entre 4 ou 5 tables différentes, avec de nombreux domaines différents. Mais je l'ai dépouillé à la partie que je ne savais pas (comment obtenir oracle pour agréger mes résultats dans une rangée). Je connais certaines choses, mais vous pouvez habituellement faire bien mieux que juste une personne si vous réduisez votre question à l'essentiel.

+0

Merci pour votre répondre mais Ma question était d'afficher tous les tags liés à un sujet plus les informations que je suis en train d'aller chercher pour chaque sujet en utilisant la même requête mentionnée dans ma question. Comment puis-je modifier cette requête sql, de sorte que toutes les balises et les informations connexes des sujets soient récupérées en utilisant une seule requête. –

+0

:) Merci encore pour votre réponse. Il n'y a pas de "tbl_topics". Seuls les évaluations (« tbl_feedbacks ») peut avoir des balises, toutes les balises sont stockées dans « tbl_tags » et la table de jointure pour des évaluations et des étiquettes est « tbl_feedbacks_tags » (A plusieurs à plusieurs) « tbl_feedbacks » contient les clés étrangères tbl_users, tbl_clients et tbl_categories. Si vous avez d'autres questions aussi, s'il vous plaît faites le moi savoir. Je vous remercie d'avoir donné votre temps précieux à mon problème. –

+0

De rien. J'ai édité ma réponse à nouveau.(BTW: cela vous donne-t-il une notification lorsque je modifie ma réponse?) –

Questions connexes