Jump to content

[SQL] Problème de limit/join ?


scouf

Recommended Posts

Bonjour,

Je cherche à faire un menu du type:

* categorie

--> item

--> item 2

* categorie 2

--> item 3

--> item 4

--> item 5

avec une requete du style:

SELECT `c`.`title`, `a`.`title` AS `article_title` ..
FROM `machn` `c`
LEFT JOIN `truc` `a`
ON `c`.`id` = |a|.`category`

Ce qui fonctionne.. mais me selectionne tous les item alors que j'aimerai les limiter à 3 maximum par categorie..

un LIMIT 0,5 ne fonctionne pas vu que dans l'exemple du haut il couperait comme ceci:

* categorie

--> item

--> item 2

* categorie 2

--> item 3

Est ce qu'il existe une solution sans passer par 50 requetes ? ;)

Merci d'avance pour le temps que vous passerez ( oui toi aussi ) à m'aider :transpi:

Link to comment
Share on other sites

Moi perso je le vois comme ca :

//Recupération des catégories
$sql="SELECT * FROM categories";
while ($don = mysql_fetch_array($sql))
{
echo $don['titre'];
$id_cat = $don['id'];

//Recupération de 3 items dans la catégorie 
$sql2="SELECT * FROM items WHERE id_item='$id_cat' LIMIT 0,3";
while ($don2=mysql_fetch_array($sql2))
{
echo $don2['item'];
}

}

2 requêtes, pas de jointures en bois, pour moi c'est le plus simple.

Link to comment
Share on other sites

Habituellement j'ai tendance à rechercher les solutions les plus simples possibles et surtout qui limitent les multiples requêtes assaisonnées de boucles PHP diverses. Dans le cas présent néanmoins la solution de Zyrik risque d'être la plus simple mais ça dépend du moteur SQL que tu utilises. Basiquement ce que tu veux faire pourrait être fait avec une sous-requête:

SELECT bla bla bla...
FROM `articles` AS a
LEFT JOIN `categories` AS c ON a.category = c.id
WHERE a.id IN (SELECT id FROM `articles` WHERE `category` = c.id LIMIT 0,3)

Malheureusement, MySQL (même la 5.1) renvoit une erreur #1235 qui précise que la clause LIMIT n'est pas encore supportée dans une sous-requête apparaissant dans un WHERE. Donc fais un test sur ton moteur (il me semble que PostgreSQL accepte bien ce genre de choses). Sinon avec MySQL je n'ai pas trop cherché, mais il est peut-être possible de remplacer cette sous-requête par une jointure sur une table temporaire dans laquelle le LIMIT apparaîtrait, mais ça devient tellement compliqué que c'est clairement moins optimisé que de se résoudre à faire N requêtes.

Link to comment
Share on other sites

Tu peux aussi fetcher tout le menu d'un coup et faire un tri en memoire du menu qui avec un 'index'* de categorie/sous-cat aussi stocké dans la table te permettra de retrouver l'ordre d'affichage.

Apres il te reste a faire une table des categories/sous-cat qui contient le label de l'index.

En 2 requetes tu fetch tout ton menu quelque soit le nombre de sous cat/cat.

*( genre 11 12 13 14 pour les sous categorie de 1, 21 22 23 etc pour les sous categories de 2 etc )

1 Table menu avec indexauto,url,label,indexcat,...

1 Table categrories avec indexauto,indexcat,label

Bien sur il faut pas seeker a la barbare la table categories pour chaque index a trouver. Il suffit de faire un dictionnaire mémoire avec en cléf l'index de la categorie, et tu affiche la clef du dictionnaire quand tu veux la categories 11 ( categorie 1 sous cat 1)

Link to comment
Share on other sites

Mmm, le problème de Scouf est d'insérer un "LIMIT 0,3" au niveau de la récupérations des items au sein de chaque catégorie: je n'ai pas regardé dans le détail, mais ton modèle de données permet-il de faire ça ou l'équivalent? Dans le cas où le modèle de données peut-être modifié, je pense qu'il est aussi possible de gérer les catégories - articles avec des listes adjacentes et de réduire le nombre de requêtes (une seule a priori) pour aller chercher les bonnes informations, mais il faudrait s'y pencher un peu plus. Si je trouve 5mn, j'essaierai...

Link to comment
Share on other sites

Mmm, le problème de Scouf est d'insérer un "LIMIT 0,3" au niveau de la récupérations des items au sein de chaque catégorie: je n'ai pas regardé dans le détail, mais ton modèle de données permet-il de faire ça ou l'équivalent? Dans le cas où le modèle de données peut-être modifié, je pense qu'il est aussi possible de gérer les catégories - articles avec des listes adjacentes et de réduire le nombre de requêtes (une seule a priori) pour aller chercher les bonnes informations, mais il faudrait s'y pencher un peu plus. Si je trouve 5mn, j'essaierai...

Je vois pas ce qui empeche de faire ca dans le trie de la table menu, avec un algorithme adéquate. Tu recupere tout et tu trie apres. Par contre c'est evident que le tri sera un peu plus compliqué, mais le temps final nécessaire de calcul sera toujours moindre que des ouvertures incessantes de socket reseau pour reveiller un service.

Link to comment
Share on other sites

Mmm, je n'avais pas compris ta méthode: quand je lisais Tu peux aussi fetcher tout le menu d'un coup, je comprenais que tu lui disais de récupérer toute la table, puis de faire le tri en PHP, alors que tu lui demandais simplement de rajouter un champs à sa table des articles, champs qui servirait à ordonner les articles au sein d'une catégorie. My mistake, je me suis paumé dans tes explications... Du coup effectivement, il suffit juste de rajouter cette colonne (appelons-là ordre, et de l'incrémenter indépendamment pour chaque catégorie:

* categorie 1

--> item 1 (ordre= 1)

--> item 2 (2)

* categorie 2

--> item 3 (1)

--> item 4 (2)

--> item 5 (3)

--> item 6 (4)

Et dans la clause WHERE il suffit effectivement de rajouter un "WHERE `ordre` < 4" pour ne conserver (au maximum), que les trois premiers articles au sein de chaque catégorie.

Link to comment
Share on other sites

Hello

Je ne m'attendais plus à d'autres reponses :love:

Alors oui c'est une bonne idée mais il resterait un problème: je veux les sous catégorie les plus recentes...

Donc je pense modifier la table à chaque ajout du genre:

"true" = afficher,

"false" ne pas afficher,

et on prend le plus vieux 'true' qu'on passe à 'false' (par categorie), ça fait qu'une requete de plus à l'ajout ...

Je vais essayer ça dès que j'aurai le temps ;) , merci =)

Link to comment
Share on other sites

Il y a plus simple: tu ajoutes un champs de type timestamp et tu précises on update current_timestamp comme attribut pour ce champs: la requête de création de la table intégrera une déclaration de ce type:

CREATE TABLE `tablename` (

...

`updated` timestamp NOT NULL default '0000-00-00 00:00:00' on update CURRENT_TIMESTAMP

...

)

Du coup tu pourras trier les articles par date décroissante, et tu auras donc logiquement les sous-catégories dans lesquelles ont été ajoutées les derniers articles. Pas de requête supplémentaire lors de l'ajout d'articles, c'est quand même plus sympa ;-)

Link to comment
Share on other sites

Uhm j'ai du mal à croire que tu a suivi le sujet et pourtant c'est le cas 8)

imaginon:

le 01/01 - titre 1 - categorie 1 - "ordre 1"

le 02/01 - titlre 2 - categorie 2 - "ordre 1"

le 03/01 - titre 3 - categorie 1 - "ordre 2"

le 04/01 - titre 4 - categorie 1 - "ordre 3"

le 05/01 - titre 5 - categorie 1 - "ordre 4"

ensuite (imaginons un affichage de 2 articles car la flemme de faire plus pour l'exemple )

SELECT * FROM `truc` WHERE `order` < 3 ORDER BY `time`

j'auais:

categorie 1

title 2

title 1

au lieu d'avoir sans le order by time:

categorie 1

title 1

title 2

alors que le resultat voulu est:

categorie 1

title 4

title 3

Bon je n'ai peut etre à nouveau pas comprit un truc, mais si ce n'est pas le cas, bah ça marche pas comme ça ^^

Sinon c'est bon je vais utiliser les solutions citées plus haut dans le poste , pas besoin nde continuer à reflechir :D

Link to comment
Share on other sites

Archived

This topic is now archived and is closed to further replies.

×
×
  • Create New...