Bonjour à tous.
Je suis actuellement en train de réaliser une application utilisant une base de données de type SQLite.
Malheureusement, je bute sur une requête. Enfin plutôt la requête fonctionne mais ne me plait pas et je me demande si il y a moyen de l'améliorer.
Donc voici le MCD des tables concernés :
CodesProduits(#idProduit, #idCode)
Codes(id, equipement, poids, prix)
Produits(id, #idCategorie, code, modele, nomProduit, libelle, image)
Je possède une liste de produit (chaque élément est un Produits.nomProduit).
Je souhaite à partir de cette liste récupérer tous les codes contenant au moins une fois chaque produit de la liste.
Voici la requête actuelle à titre d'exemple :
SELECT DISTINCT CodesProduits.idCode
FROM CodesProduits
WHERE CodesProduits.idCode IN(
SELECT DISTINCT CodesProduits.idCode
FROM CodesProduits, Produits
WHERE Produits.id = CodesProduits.idProduit
AND Produits.nomProduit = "Simple Dent Standard"
)
AND CodesProduits.idCode IN(
SELECT DISTINCT CodesProduits.idCode
FROM CodesProduits, Produits
WHERE Produits.id = CodesProduits.idProduit
AND Produits.nomProduit = "4"
)
Exemple de résultat :
5
6
10
11
Comme vous pouvez le voir, je fais une sous requête par produit de la liste. Je trouve ça assez lourd mais ne vois pas comment améliorer ça. La requête est généré par l'application donc l'écrire est simple mais c'est plutôt pour les temps d'exécution en cas de grosses listes de produits que je m'inquiète.
Donc voilà si quelqu'un a une idée je suis preneur.
Merci d'avance
SELECT DISTINCT CodesProduits.idCode
FROM CodesProduits, Produits
WHERE Produits.id = CodesProduits.idProduit
AND (Produits.nomProduit = "Simple Dent Standard"
OR Produits.nomProduit = "4")
J'avais commencé sur cette requète mais là tu prends tous les codes qui n'ont qu'un seul des produits dans la liste (OR)
En fait je cherche les codes qui ont TOUS les produits de la liste.
Je possède une liste de produit (chaque élément est un Produits.nomProduit).
Je souhaite à partir de cette liste récupérer tous les codes contenant au moins une fois chaque produit de la liste.
Ça a l'air assez clair...
Le plus simple :
SELECT CodesProduits.idCode
FROM CodesProduits, Produits
WHERE Produits.id = CodesProduits.idProduit
AND Produits.nomProduit = "Simple Dent Standard"
INTERSECT
SELECT CodesProduits.idCode
FROM CodesProduits, Produits
WHERE Produits.id = CodesProduits.idProduit
AND Produits.nomProduit = "4"
Note que INTERSECT vire les doublons.
Mais si t'as une liste assez longue ça devient vite énorme. Il y a mieux.
Note que tu devrais utiliser la syntaxe de jointure standard JOIN ON (Produits.id = CodesProduits.idProduit) et utiliser les mêmes noms de colonnes pour les colonnes de relation (idProduit dans les deux tables).
De plus il manque une table : celle avec la liste des codes. Dans ce cas, CodesProduits est simplement une relation N-N entre Codes et Produits. T'es pas obligé de la mettre mais ça peut servir.
Je suppose que :
- Produits.nomProduit est UNIQUE
- (idCode,idProduit) est la clé primaire de CodesProduits ou au minimum UNIQUE
Donc :
SELECT idCode
FROM Produits p
JOIN CodesProduits cp USING (idProduit)
WHERE p.nomProduit IN ("4","Simple Dent Standard")
GROUP BY idCode
HAVING count(*) = 2;
Comme dans CodesProduits on a une contrainte d'unicité sur (idCode,idProduit), il ne peut pas y avoir de doublons, donc comme la longueur de la liste est 2, tout code qui a count(*)=2 (donc 2 produits) correspond.
Merci pour cette réponse très complète ça m'as beaucoup aidé.
Donc pour répondre à tes questions, Produits.nomProduit est bien unique.
(idCode, idProduit) est la clé primaire de CodesProduits et le couple est donc forcément unique.
Ta dernière requête fonctionne très bien et j'avoue que je la trouve très classe dans sa manière de faire.
J'aurais quelques questions cependant :
Imaginons que j'ai une liste de 10 produits il faut que je recherche tous les codes ayant count(*) = 10 ?
Sinon, merci beaucoup je devrais pouvoir finaliser les derniers détails de mon logiciel
Oui, le count(*) doit être égal à la longueur de la liste (mais si tu mets des doublons dans ta liste, le IN() le vire donc tu auras un résultat vide)
Amélioration requête SQL
× Après avoir cliqué sur "Répondre" vous serez invité à vous connecter pour que votre message soit publié.
× Attention, ce sujet est très ancien. Le déterrer n'est pas forcément approprié. Nous te conseillons de créer un nouveau sujet pour poser ta question.
Tutoriel complet MySQL !
Tutoriel complet MySQL !