Question pour une requête MYSQL

  • Auteur de la discussion Auteur de la discussion noren
  • Date de début Date de début
WRInaute accro
Bonjour

Voilà le problème

J'ai une table suivante

id_taxon
id_article

Les 2 id forment une clé primaire.
On peut avoir un même article dans plusieurs taxons (taxon = rubrique, catégorie ou tag).

Exemple

TAXON - ARTICLE
rub A - article A
rub B - article A

soit

id_taxon - id_article
1 - 1
2 - 1
3 - 2
1 - 3
2 - 2

Ma question est la suivante comment arriver à récupérer tous les articles qui sont dans le Taxon A et B. Sachant que ceux qui sont uniquement dans A ou dans dans B ne m'intéressent pas.

je sais pas si je suis assez clair :?

j'essaye de me baser sur Wordpress, en utilisant le système des taxons.
 
Nouveau WRInaute
C'est pas tres clair, tu as un nombre de défini de rubrique? ou tu veux les articles qui sont présents dans toutes les rubriques ?

Je balance une requête pour faire avancer ton truc en partant du principe que tu veux les articles des rubriques A et B avec la rub A qui correspond a id_taxon = 1 et la rub B qui correspond a id_taxon = 2

select distinct (id_article)
from table
where id_taxon = 1
and id_taxon = 2
 
WRInaute accro
lavieasaigon a dit:
where id_taxon = 1 and id_taxon = 2
Je suis pas certain que ça passe car pour un id donnée le record n'aura pas 2 id_taxon (mais faut vérifier)
Sinon voir aussi du côté id_taxon IN(1,2)
 
WRInaute accro
lavieasaigon a dit:
C'est pas tres clair, tu as un nombre de défini de rubrique? ou tu veux les articles qui sont présents dans toutes les rubriques ?

Je balance une requête pour faire avancer ton truc en partant du principe que tu veux les articles des rubriques A et B avec la rub A qui correspond a id_taxon = 1 et la rub B qui correspond a id_taxon = 2

select distinct (id_article)
from table
where id_taxon = 1
and id_taxon = 2

merci.

Non justement je ne veux pas tous les articles de la rubrique A et de la rubrique B, mais uniquement les articles qui sont aussi bien dans A que dans B.

exemple j'ai un article appelé Y qui se trouve aussi bien dans la rubrique A et dans la rubrique B. et un autre article Z qui se trouve que dans la rubrique A.

je veux que ressorte uniquement l'article Y.

Donc en effet je pense pas que ta requête passera avec ou sans DISTINCT

zeb a dit:
Je suis pas certain que ça passe car pour un id donnée le record n'aura pas 2 id_taxon (mais faut vérifier)
Sinon voir aussi du côté id_taxon IN(1,2)

En effet il est possible que le IN puisse fonctionner faudra que j'essaye. je vous tiens au courant dans la journée
Les IN ne sont pas trop gourmands en terme de ressources?

merci.

Si d'autres personnes ont d'autres pistes au cas ou je suis preneur. je trouve que cette méthode de regrouper les Taxons est pratiques mais peut parfois compliqyer les choses dans de rares cas :?

En fait pour plus de précisions j'ai ceci :

t_taxons
id_taxon (clé primaire)
taxon
taxonomie (j'indique ici si c'est une rubrique, un tag, une catégorie etc.)
description
..
parent_id (id du taxon parent)

t_articles
id_article (clé primaire)
titre
description
blablabla
...

t_taxon_article (les 2 id sont la clé primaire)
id_taxon
id_article

comme indiqué j'essaye de me baser le plus possible (du moins dans ce cas là) sur la structure de Wordpress.
 
WRInaute accro
@zeb :

j'ai essayé ça : SELECT * FROM t_taxon_article WHERE id_taxon in (71,12)

ça me retourne tous les articles qui sont soit dans la rubrique 71 soit dans la 12.

hors mois je veux ceux qui sont forcément dans la 71 et la 12 pas les autres :/

Arf j'avais une lueur d'espoir :(
 
WRInaute accro
et un select imbriqué, du genre ?
Code:
 SELECT * FROM t_taxon_article WHERE id_taxon =71 and taxon in (SELECT taxon  FROM t_taxon_article WHERE id_taxon=72)
pas sur de la formulation exacte
 
Nouveau WRInaute
Tiens tu peux essayer ça.
C'est la requête pour avoir les articles qui sont uniquement dans les catégories 71 et 72 (et pas les autres):
Le distinct c'est juste pour enlever les doublons, c'est pas indispensable.

Code:
SELECT * 
FROM t_taxon_article 
WHERE id_taxon = 71 
and id_taxon = 72
and id_article not in (SELECT id_article 
				FROM t_taxon_article 
				WHERE id_taxon not in (72,71))
 
WRInaute accro
Un truc du genre :
SELECT id_article FROM table GROUP BY id_article HAVING (id_taxon = 1 AND id_taxon = 2)

C'est de la pèche a la ligne pas de la programmation, je donne ce qui me passe par la tête (c'est pas très pro comme démarche :D )
 
WRInaute passionné
Code:
SELECT DISTINCT id_article FROM table WHERE id_taxon = "71" and id_article IN (SELECT DISTINCT id_article FROM table WHERE id_taxon = "72")

Chaque problème se décompose et se résout étape par étape :)
 
WRInaute accro
merci je vais essayer tout ça dans la journée, je vous tiens au courant :mrgreen:

D'ailleurs j'en profite pour vous demander, pensez vous en effet que ça soit judicieux de regrouper tout ce qui est taxon (categories, rubriques, tags...) dans 2 seules tables?

Ou est-il préférable de faire de la sorte :

t_articles
id_article
titre
description
blablabla
...

t_categorie
id_cat
titre
permalien
blablabla

t_cat_article
id_cat
id_article

t_rubrique
id_rub
titre
description
permalien
blablabla

t_rub_article
id_rub
id_article

t_tag
id_tag
titre
description
permalien
blablabla

t_tag_article
id_tag
id_article

Avec cette seconde solution on constate qu'on peut se retrouver avec un grand nombre de tables (maintenances plus lourdes), mais également beaucoup de répétitions : titre, description, etc.
par contre je pense que les requêtes d'extractions seront plus simples.

La solution de la table taxon me parait plus légère et plus souple que cette solution de créer des tables pour chaque type de classement. Inconvénient ça rend les requêtes peut être un poil plus complexes et peut être plus gourmandes.

Avec la table taxon je pourrait facilement par exemple ajouter pleins d'autres types de classements très rapidement (fournisseurs, éditeurs etc.) sans avoir besoin d'ajouter de nouvelles tables voir d'implanter de nouvelles pages en backoffice (hormis quelques retouches).

Qu'elle est votre avis la dessus?
 
WRInaute accro
merci à tous.

La solution de Lambi512 et Leonick fonctionne :wink:

Bon j'ai encore quelques problèmes à régler afin d'être certain que je suis dans la bonne voie en utilisant cette table taxon :/
Solution pas évidente du tout à utiliser pour les extractions de données :?

je suis pas encore sorti de l'auberge...
 
WRInaute accro
noren a dit:
La solution de Lambi512 et Leonick fonctionne :wink:
Le seul truc qui me dérange dans cette solution avec la seconde requête imbriquée c'est que si tu veux tes id avec en plus le taxon 23 ET OU le 24 tu fait comment ? Par ce que concrètement le second select fait bien le travail pas de souci mais c'est pas "généralisable proprement" dans une boucle ou alors faudrait l'écrire autrement genre :

SELECT DISTINCT id_article FROM table
WHERE
id_article IN (SELECT DISTINCT id_article FROM table WHERE id_taxon = "71") AND
id_article IN (SELECT DISTINCT id_article FROM table WHERE id_taxon = "72")

pour la généraliser sous cette forme au travers d'une boucle de construction :

SELECT DISTINCT id_article FROM table
WHERE
id_article IN (SELECT DISTINCT id_article FROM table WHERE id_taxon = "71") AND
id_article IN (SELECT DISTINCT id_article FROM table WHERE id_taxon = "23") AND
id_article IN (SELECT DISTINCT id_article FROM table WHERE id_taxon = "24") AND
.......
id_article IN (SELECT DISTINCT id_article FROM table WHERE id_taxon = "72")

D'où a mon avis la recherche d'une solution plus "sport" sou forme de liste d'id de taxon ou un truc dans le genre.

Bon c'est pas que je veuille mettre le souk mais je suis un peu taquin quand même :D
 
WRInaute accro
Oui je vois ce que tu veux dire en effet. Et faire des tonnes de requêtes imbriquées je suis pas certain que ça soit très jojo :/

En effet si je veux afficher les articles qui sont dans les rubriques A, B et C etc. j'en arrive vite à un grand nombre de requêtes imbriqués :?

Donc si une personne arrive à trouver une meilleur solution je suis preneur.

Et voici un casse tête qui à mon gout est encore plus complexe (pour moi en tout cas, je suis un peu rouillé en programmation) et qui est dans la même ligné.

Exemple :

Dans la page de la rubrique "Fringues" (id_taxon=1)

je souhaite afficher ceci dans cette page :

liste des 10 top articles (id_article) de la rubrique caleçons (id_taxon=2)
liste des 10 top articles de la rubrique chaussettes (id_taxon=3)
etc.

Rappel des tables pour ceux qui aiment les casses têtes :

t_taxons
id_taxon
taxon (fringues, caleçons, chaussettes..)
taxonomie (indique ici si c'est une rubrique, un tag, une catégorie etc.)
description
..
parent_id (id du taxon parent)

t_articles
id_article
article
description
blablabla
...

t_taxon_article (les 2 id sont la clé primaire)
id_taxon
id_article


PS : j'ai choisi d'appelé RUBRIQUE ces 3 taxons "fringues", "caleçons" et "chaussettes" pour que ça soit plus clair pour vous. Mais ça résume assez bien le problème. J'aurais pu dire CATEGORIE pour "fringue" mais ça revient strictement au même, car les catégories sont gérés par la même table t_taxon ;)

Je me prend la tête depuis plusieurs jours avec cette fichu table qui parait pourtant toujours fort pratique en de nombreux points.
 
WRInaute passionné
J'avoue que j'ai mis la solution la plus simple, celle qui viens sans se prendre la tête dessus, mais c'est clair que les "IN" sont très gourmands à l'exécution. Il faudrait faire une jointure, ce qui est beaucoup plus propre, mais sans avoir tous les éléments sous la main c'est plus dur de comprendre.

Essaye ça, une fake jointure, mais qui sera surement moins gourmande. Une fois je suis même tombé sur une version de MySQL qui ne supportais pas les "IN".

Code:
SELECT DISTINCT t.id_article FROM t_taxon_article t, t_taxon_article t2 WHERE t.id_article = t2.id_article AND t.id_taxon = "71" AND t2.id_taxon = "72"

Le seul truc qui me dérange dans cette solution avec la seconde requête imbriquée c'est que si tu veux tes id avec en plus le taxon 23 ET OU le 24 tu fait comment ? Par ce que concrètement le second select fait bien le travail pas de souci mais c'est pas "généralisable proprement" dans une boucle ou alors faudrait l'écrire autrement genre :

Je changerais la fin de ta phrase comme ceci : "ou alors il faudrait repenser le SGBD..."
 
WRInaute accro
Super lambi521 merci, en effet ta 2ème proposition est clairement bien plus performante.

on passe d'environ 0.0013 s (solution avec le IN)
à 0,0005 (sans le IN)

3 fois plus performant

lambi521 j'en profites pour te demander, penses tu que cette solution d'utiliser une seule table pour inclure l'ensemble des taxons (categories, tags, rubriques...) soit un bon choix?

Ou penses tu qu'il serait préférable d'avoir une table pour les catégorie, une table pour les rubriques, une table pour les tags etc. ?

est-ce que ce type de requête est considéré comme propre et couramment utilisée :

SELECT DISTINCT t.id_article FROM t_taxon_article t, t_taxon_article t2 WHERE t.id_article = t2.id_article AND t.id_taxon = "71" AND t2.id_taxon = "72"

Est-ce que ce type de requête ne risque pas d’être refusé dans de prochaines version de Mysql (je sais question stupide mais bon...)

PS : et avec un LEFT JOIN ça donnerait quoi? :P (je voudrais comparer les performances)
 
WRInaute accro
Alors j'ai essayé avec Jointure

SELECT DISTINCT t.id_article
FROM t_taxon_article t
LEFT JOIN t_taxon_article t2 ON t.id_article = t2.id_article
WHERE t.id_taxon = "12" AND t2.id_taxon = "71";

je sais pas si la syntaxe est bonne mais en tout cas ça à l'air de fonctionner. Mais étonnamment ça m'a semblait un poil moins performant que la version "fake jointure" ;)

0.0006 - 0,0007 (avec des pointes à 0.0011)

Je ne sais pas trop pourquoi, pourtant c'est ce qui semble le plus propre...
 
WRInaute accro
en fait, une jointure partielle left ou right sera plus gourmande qu'une jointure complète, car même sans correspondance à droite la ligne est extraite : enlève ton where et effectue ta requête et compare le nombre de lignes renvoyées avec le left et sans
 
WRInaute accro
Alors j'ai essayé ceci :
SELECT DISTINCT t.id_article
FROM t_taxon_article t
JOIN t_taxon_article t2 ON t.id_bloc = t2.id_article AND
WHERE t.id_taxon = "12" AND t2.id_taxon = "71"

C'est aussi gourmand que le LEFT JOIN

J'ai essayé également ceci

SELECT DISTINCT t.id_article
FROM t_taxon_article t
JOIN t_taxon_article t2 ON t.id_article = t2.id_article
AND t.id_taxon = "12"
AND t2.id_taxon = "71"

c'ets pareil je suis dans une moyenne de 0.0006 s, je pense que c'est plus que correct pour une requête.

En gros les 3 solutions (sans jointure, jointure partiel, ou jointure totale) semblent équivalentes en tout cas par rapport à la quantité de données stockées dans mes tables pour le test.

Rien à voir avec la solution du select imbriqué extrêmement gourmande. merci zeb d'avoir souligné ce problème concernant ce type de requêtes :wink:

Je devrais donc pouvoir m'en sortir avec ma table Taxon sans trop trop de problème, j'avais pas penser à la solution des ALIAS pour pouvoir utiliser 2 fois la même table dans une jointure :wink:

Un grand merci à vous
 
Discussions similaires
Haut