Twitter iPhone pliant OnePlus 11 PS5 Disney+ Orange Livebox Windows 11

SELECT sur plusieurs tables et LIMIT

9 réponses
Avatar
loufoque
Bonjour,

Pour un blog, j'essaie d'afficher la liste des derniers billets en
indiquant pour chacun les catégories auxquelles il appartient.
Je vais tenter d'expliquer mon problème, voici ma structure

billets
- id
- date

billcats
- id_billet
- id_categorie

categories
- id
- nom

Et donc je lie un certain nombre de catégories définies dans categories
aux différents billets au travers de la table billcats.

Pour afficher, je fais donc cette requête :

SELECT a.id, a.date, c.nom
FROM billets AS a, billcats AS b, categories AS c
WHERE a.id = b.id_billet AND b.id_categorie = c.id
ORDER BY a.date DESC LIMIT 5

J'obtiens donc 5 enregistrements, avec autant de fois le billet qu'il
est associé à des catégories mais avec à chaque fois la catégorie
différente. Donc bon je "dédoublonne" avec un traitement en PHP, mais au
final je n'ai plus 5 enregistrements.

Il y a-t-il une meilleure façon de procéder ? Comment puis-je faire pour
avoir au final les 5 enregistrements les plus récents avec pour chacun
leurs catégories associées ?

Merci d'avance pour votre aide.

9 réponses

Avatar
Antoine Dinimant
J'obtiens donc 5 enregistrements, avec autant de fois le billet qu'il
est associé à des catégories mais avec à chaque fois la catégorie
différente. Donc bon je "dédoublonne" avec un traitement en PHP, mais au
final je n'ai plus 5 enregistrements.

Il y a-t-il une meilleure façon de procéder ? Comment puis-je faire pour
avoir au final les 5 enregistrements les plus récents avec pour chacun
leurs catégories associées ?



avec un SGBD qui accepte les sous-requêtes, ça donnerait :

SELECT a.id, a.date, c.nom
FROM billets AS a, billcats AS b, categories AS c
WHERE a.id = b.id_billet AND b.id_categorie = c.id
ORDER BY a.date DESC LIMIT 5

Select tmp.id, tmp.date, c.nom
From (
Select a.id, a.date
From billets a
Order By a.date Desc
Limit 5
) tmp
, billcats b
, categories c
Where tmp.id = b.id_billet
And b.id_categorie = c.id
Order By tmp.date Desc
, c.nom

Avec MySQL, tu peux lancer la sous-requête dans un
CREATE TEMPORARY TABLE tmp
SELECT ...

puis lancer la requête principale

Select tmp.id, tmp.date, c.nom
From tmp, billcats b , categories c
Where ...

Ce qui aura l'inconvénient de doublonner à nouveau, même si tes données
seront + juste. Si tu veux éviter ça, tu relances une requête de
recherche des catégories pour chacun de tes billets...

$sql = "Select c.nom
From billcats b , categories c
Where b.id_categorie = c.id
And b.id_billet = $id "
Avatar
Etienne SOBOLE
"loufoque" a écrit dans le message de news:
c7iqh0$dkc$

SELECT a.id, a.date, c.nom
FROM billets AS a, billcats AS b, categories AS c
WHERE a.id = b.id_billet AND b.id_categorie = c.id
ORDER BY a.date DESC LIMIT 5

J'obtiens donc 5 enregistrements, avec autant de fois le billet qu'il
est associé à des catégories mais avec à chaque fois la catégorie
différente. Donc bon je "dédoublonne" avec un traitement en PHP, mais au
final je n'ai plus 5 enregistrements.



y a quoi dans tes tables a l'origine?
Etienne
Avatar
loufoque
Antoine Dinimant wrote:

avec un SGBD qui accepte les sous-requêtes, ça donnerait [...]


Je ne suis pas trop habitué aux sous-requêtes, mais bon ça fonctionne
parfaitement.
En fait fondamentalement le principe c'est de créer une "table"
temporaire à partir d'une requête de type SELECT. Ça peut permettre des
trucs assez intéressants...
(Heureusement, j'utilise depuis peu des SGBDs qui supportent les
sous-requêtes)
Au fait, c'est bien standard SQL92 ?

Ce qui aura l'inconvénient de doublonner à nouveau, même si tes données
seront + juste. Si tu veux éviter ça, tu relances une requête de
recherche des catégories pour chacun de tes billets...


Oui, j'avais bien sûr envisagé cette solution, mais je ne la trouvais
pas élégante. Surtout que le "LIMIT 5" peut très bien devenir un "LIMIT
20". Il vaut mieux éviter d'avoir un nombre important de requêtes, et
surtout d'en avoir un nombre variable.

Enfin en fait je recherche la solution la plus performante. Je ne sais
pas ce que vaut une requête avec des sous-requêtes en terme de performance.

Bon en tous cas merci pour tout, parce que non seulement j'arrive à
faire marcher ce que je voulais mais en plus j'ai appris le principe des
sous-requêtes :).
Avatar
Antoine Dinimant
Je ne suis pas trop habitué aux sous-requêtes, mais bon ça fonctionne
parfaitement.
En fait fondamentalement le principe c'est de créer une "table"
temporaire à partir d'une requête de type SELECT. Ça peut permettre des
trucs assez intéressants...



ce n'est que le type de sous-requête le plus simple, dit "dans le From"

(Heureusement, j'utilise depuis peu des SGBDs qui supportent les
sous-requêtes)



tu es sous quoi ?

Au fait, c'est bien standard SQL92 ?



'bsolument !

Ce qui aura l'inconvénient de doublonner à nouveau, même si tes
données seront + juste. Si tu veux éviter ça, tu relances une requête
de recherche des catégories pour chacun de tes billets...



Oui, j'avais bien sûr envisagé cette solution, mais je ne la trouvais
pas élégante. Surtout que le "LIMIT 5" peut très bien devenir un "LIMIT
20". Il vaut mieux éviter d'avoir un nombre important de requêtes, et
surtout d'en avoir un nombre variable.



je t'approuve tout à fait ! dans l'ensemble, un traitement PHP est tj
plus rapide qu'un aller-retour entre PHP et une BDD

Enfin en fait je recherche la solution la plus performante. Je ne sais
pas ce que vaut une requête avec des sous-requêtes en terme de performance.



ça dépend de ton SGBD et du type de sous-requête... Dans le From et sans
corrélation, normalement ça ne pose aucun problème

Bon en tous cas merci pour tout, parce que non seulement j'arrive à
faire marcher ce que je voulais mais en plus j'ai appris le principe des
sous-requêtes :).



you welcome !
Avatar
loufoque
Etienne SOBOLE wrote:
y a quoi dans tes tables a l'origine?



Je pensais avoir bien expliqué...
Enfin de toutes façons c'est bon mon problème résolu.
Avatar
loufoque
Antoine Dinimant wrote:

tu es sous quoi ?



MySQL 4.1 sous Windows, PostgreSQL sous Linux (enfin j'ai pas testé la
requête avec mais ça devrait fonctionner) et SQLite.
Mais ça ne marche pas avec SQLite, qui en fait ne supporte que les
sous-requêtes statiques (enfin je pense que ça vient de là, il me dit
que tmp.id n'existe pas)
Avatar
Antoine Dinimant
Antoine Dinimant wrote:

tu es sous quoi ?




MySQL 4.1 sous Windows,



ils ont enfin implanté les sous-requêtes en MySQL 4.1 ? Parce qu'en 4.0,
elles n'y sont pas...

PostgreSQL sous Linux (enfin j'ai pas testé la
requête avec mais ça devrait fonctionner) et SQLite.
Mais ça ne marche pas avec SQLite, qui en fait ne supporte que les
sous-requêtes statiques (enfin je pense que ça vient de là, il me dit
que tmp.id n'existe pas)

Avatar
loufoque
Antoine Dinimant wrote:
ils ont enfin implanté les sous-requêtes en MySQL 4.1 ? Parce qu'en 4.0,
elles n'y sont pas...



MySQL4.1 est encore au stade de développement
Voici les nouvelles fonctionnalités [en] :
http://www-fr.mysql.com/doc/en/Nutshell_4.1_features.html
Avatar
Antoine Dinimant
MySQL4.1 est encore au stade de développement
Voici les nouvelles fonctionnalités [en] :
http://www-fr.mysql.com/doc/en/Nutshell_4.1_features.html



merci !