Partage
  • Partager sur Facebook
  • Partager sur Twitter

Amélioration requête SQL

Fonctionnel mais pas beau !

Sujet résolu
    4 mai 2011 à 15:37:40

    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
    • Partager sur Facebook
    • Partager sur Twitter
      4 mai 2011 à 15:46:32

      SELECT DISTINCT CodesProduits.idCode
      FROM CodesProduits, Produits
      WHERE Produits.id = CodesProduits.idProduit 
      AND (Produits.nomProduit = "Simple Dent Standard" 
          OR  Produits.nomProduit = "4")
      


      Non ?

      • Partager sur Facebook
      • Partager sur Twitter
        4 mai 2011 à 15:49:25

        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.

        Merci quand même
        • Partager sur Facebook
        • Partager sur Twitter
          4 mai 2011 à 15:52:05

          Heu... Tu saurais donner les tables et une partie de leur contenu alors ?? Je vois VRAIMENT pas ce que tu veux...
          • Partager sur Facebook
          • Partager sur Twitter
            4 mai 2011 à 15:59:51

            Okay :
            Donc voici 2 screens de mes tables :
            CodesProduits
            Produits

            La requête que j'avais donné en premier me donnait la liste des codes ayant au moins le nom du produit 1 et du produit 2 dans le même code.

            J'espère avoir été plus clair

            • Partager sur Facebook
            • Partager sur Twitter
              4 mai 2011 à 17:36:33

              Citation : vince85

              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.
              • Partager sur Facebook
              • Partager sur Twitter
                4 mai 2011 à 18:41:54

                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 ;)
                • Partager sur Facebook
                • Partager sur Twitter
                  4 mai 2011 à 18:52:41

                  > Imaginons

                  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)
                  • Partager sur Facebook
                  • Partager sur Twitter

                  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.
                  • Editeur
                  • Markdown