IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Langage SQL Discussion :

Récupérer le bon tarif


Sujet :

Langage SQL

  1. #1
    Membre régulier
    Homme Profil pro
    Développeur Web
    Inscrit en
    Septembre 2005
    Messages
    197
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Ille et Vilaine (Bretagne)

    Informations professionnelles :
    Activité : Développeur Web
    Secteur : Services à domicile

    Informations forums :
    Inscription : Septembre 2005
    Messages : 197
    Points : 121
    Points
    121
    Par défaut Récupérer le bon tarif
    Bonjour,
    J'ai un souci concernant la formulation d'une requete. Celle-ci doit me retourner un montant bien précis qui provient d'une table "tarifs" pour un produit donné.
    Ma table a les champs suivants :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    +------------+-------+----------+
    | id_produit | prix  | quantite |
    +------------+-------+----------+
    |          1 | 10.00 |        1 |
    |          1 |  8.00 |        5 |
    |          1 |  6.00 |       10 |
    |          1 |  4.00 |       15 |
    +------------+-------+----------+
    Dnas ma table panier j'ai une quantité commandée de 6 pour l'article avec l'id_produit = 1, or je n'arrive qu'a récupérer les tarifs à "6.00" et "4.00"
    avec la requête ci-dessous :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    SELECT t.prix, t.quantite
    FROM panier AS p
    LEFT JOIN tarifs AS t ON p.id_produit = t.id_produit
    WHERE t.quantite >= p.quantite;
    Vous me direz que ce comportement est normal vu que j'utilise '>=' mais dans ce cas comment récupérer la ligne avec le tarif = à "8.00"
    Cela pet-il se faire en SQL ou dois-je récupérer toutes les lignes de tarifs pour le produits et passer ensuite avec un triage au niveau du PHP ?

    Merci de votre aide.

  2. #2
    Expert éminent sénior
    Homme Profil pro
    Responsable Données
    Inscrit en
    Janvier 2009
    Messages
    5 198
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 50
    Localisation : France, Hérault (Languedoc Roussillon)

    Informations professionnelles :
    Activité : Responsable Données

    Informations forums :
    Inscription : Janvier 2009
    Messages : 5 198
    Points : 12 774
    Points
    12 774
    Par défaut
    Bonjour,
    Je pense que la réponse est dans la question:
    Citation Envoyé par Shiva Voir le message
    Vous me direz que ce comportement est normal vu que j'utilise '>='
    Le résultat correspond parfaitement à la requête. Tu demandes les lignes dont la quantité est >= à 6, le moteur renvoie toutes les lignes dont la quantité est >= 6...
    Donc je me mets à la place de la base:
    Qu'est-ce qui fait que tu veux récupérer le prix à 8.00 ? Quels critères doit-elle remplir pour que je la renvoie ?

    Tatayo.

    P.S. Petite remarque:
    Code SQL : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    SELECT t.prix, t.quantite
    FROM panier AS p
    LEFT JOIN tarifs AS t ON p.id_produit = t.id_produit
    WHERE t.quantite >= p.quantite;

    Vu que tu as un critère sur t dans le where, la jointure externe se transforme en jointure interne ! Il faut déplacer la condition dans la jointure:
    Code SQL : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    SELECT t.prix, t.quantite
    FROM panier AS p
    LEFT JOIN tarifs AS t ON p.id_produit = t.id_produit and t.quantite >= p.quantite;

  3. #3
    Membre régulier
    Homme Profil pro
    Développeur Web
    Inscrit en
    Septembre 2005
    Messages
    197
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Ille et Vilaine (Bretagne)

    Informations professionnelles :
    Activité : Développeur Web
    Secteur : Services à domicile

    Informations forums :
    Inscription : Septembre 2005
    Messages : 197
    Points : 121
    Points
    121
    Par défaut
    Il faut savoir que l'exemple que je donne avec les quantités (et les prix) n'est pas fixe, donc à la place de 1, 5, 10 et 15 je pourrais très bien avoir 1, 10, 30, 50. Sinon, je viens de tester avec cette requête :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    SELECT t.prix, MAX(t.quantite)
    FROM panier AS p
    LEFT JOIN tarifs AS t ON p.id_produit = t.id_produit AND t.quantite <= p.quantite;
    Le résultat obtenu est bon mais est-ce correctement écrit ? Il y a peut-être une autre manière de faire ?

    --> Non en fait cette requête n'est pas bonne du tout, retour case départ...

  4. #4
    Modérateur
    Avatar de Waldar
    Homme Profil pro
    Customer Success Manager @Vertica
    Inscrit en
    Septembre 2008
    Messages
    8 452
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 46
    Localisation : France, Val de Marne (Île de France)

    Informations professionnelles :
    Activité : Customer Success Manager @Vertica
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2008
    Messages : 8 452
    Points : 17 820
    Points
    17 820
    Par défaut
    Si le prix est toujours dégressif avec l'augmentation de quantité, vous pouvez écrire ceci je pense :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
      SELECT p.id_produit, p.quantite, COALESCE(MAX(t.prix), 0) as prix
        FROM panier AS p
             LEFT OUTER JOIN tarifs AS t
               ON t.id_produit = p.id_produit
              AND t.quantite  >= p.quantite
    GROUP BY p.id_produit, p.quantite

  5. #5
    Membre régulier
    Homme Profil pro
    Développeur Web
    Inscrit en
    Septembre 2005
    Messages
    197
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Ille et Vilaine (Bretagne)

    Informations professionnelles :
    Activité : Développeur Web
    Secteur : Services à domicile

    Informations forums :
    Inscription : Septembre 2005
    Messages : 197
    Points : 121
    Points
    121
    Par défaut
    Citation Envoyé par Waldar Voir le message
    Si le prix est toujours dégressif avec l'augmentation de quantité, vous pouvez écrire ceci je pense :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
      SELECT p.id_produit, p.quantite, COALESCE(MAX(t.prix), 0) as prix
        FROM panier AS p
             LEFT OUTER JOIN tarifs AS t
               ON t.id_produit = p.id_produit
              AND t.quantite  >= p.quantite
    GROUP BY p.id_produit, p.quantite
    En fait non ça ne ramène pas la bonne ligne. Le prix retourné est "6.00". Celui-ci n'est pris en compte que si le nombre d'articles dans le panier est >= à 10.

  6. #6
    Rédacteur

    Avatar de SQLpro
    Homme Profil pro
    Expert bases de données / SQL / MS SQL Server / Postgresql
    Inscrit en
    Mai 2002
    Messages
    21 768
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Var (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Expert bases de données / SQL / MS SQL Server / Postgresql
    Secteur : Conseil

    Informations forums :
    Inscription : Mai 2002
    Messages : 21 768
    Points : 52 719
    Points
    52 719
    Billets dans le blog
    5
    Par défaut
    Utilisez une vue, ce sera plus facile... En principe on devrait toujours développer les application à partir de vues et non directement sur des tables .

    Démonstration :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    CREATE TABLE T_TARIF
    (id_produit   INT NOT  NULL,
     quantite     INT NOT NULL,
     prix         DECIMAL(16,2) NOT NULL,
     CONSTRAINT PK_TRF PRIMARY KEY (id_produit, quantite));
    GO
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    INSERT INTO T_TARIF 
    VALUES (1, 1,  10.00),
    (1,  5, 8.00),
    (1, 10 , 6.00), 
    (1, 15, 4.00);
    GO
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    CREATE VIEW V_TARIF
    AS
    SELECT id_produit, quantite AS quantie_min,
           COALESCE((SELECT MIN(quantite) - 1
                     FROM   T_TARIF
                     WHERE  quantite > T.quantite), 2000000000) AS quantite_max,
           prix 
    FROM   T_TARIF AS T
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
     
    id_produit  quantie_min quantite_max prix
    ----------- ----------- ------------ ----------
    1           1           4            10.00
    1           5           9            8.00
    1           10          14           6.00
    1           15          2000000000   4.00
    Dès lors les requêtes sur la vue deviennent triviales :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    SELECT p.id_produit, p.quantite, prix
    FROM   panier AS p
           INNER JOIN V_TARIF AS T
                 ON p.id_produit = T.id_produit
                    AND P.quantite BETWEEN T.quantie_min 
                                       AND T.quantie_mAX;
    A +
    Frédéric Brouard - SQLpro - ARCHITECTE DE DONNÉES - expert SGBDR et langage SQL
    Le site sur les SGBD relationnels et le langage SQL: http://sqlpro.developpez.com/
    Blog SQL, SQL Server, SGBDR : http://blog.developpez.com/sqlpro
    Expert Microsoft SQL Server - M.V.P. (Most valuable Professional) MS Corp.
    Entreprise SQL SPOT : modélisation, conseils, audit, optimisation, formation...
    * * * * * Expertise SQL Server : http://mssqlserver.fr/ * * * * *

  7. #7
    Modérateur
    Avatar de Waldar
    Homme Profil pro
    Customer Success Manager @Vertica
    Inscrit en
    Septembre 2008
    Messages
    8 452
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 46
    Localisation : France, Val de Marne (Île de France)

    Informations professionnelles :
    Activité : Customer Success Manager @Vertica
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2008
    Messages : 8 452
    Points : 17 820
    Points
    17 820
    Par défaut
    Citation Envoyé par Shiva Voir le message
    En fait non ça ne ramène pas la bonne ligne. Le prix retourné est "6.00". Celui-ci n'est prit en compte que si le nombre d'articles dans le panier est >= à 10.
    Ok, par contre que ça ne vous empêche pas de réfléchir, dans ce cas il suffit d'inverser la solution :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     SELECT p.id_produit, p.quantite, COALESCE(MIN(t.prix), 0) AS prix
        FROM panier AS p
             LEFT OUTER JOIN tarifs AS t
               ON t.id_produit = p.id_produit
              AND t.quantite  <= p.quantite
    GROUP BY p.id_produit, p.quantite

  8. #8
    Membre régulier
    Homme Profil pro
    Développeur Web
    Inscrit en
    Septembre 2005
    Messages
    197
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Ille et Vilaine (Bretagne)

    Informations professionnelles :
    Activité : Développeur Web
    Secteur : Services à domicile

    Informations forums :
    Inscription : Septembre 2005
    Messages : 197
    Points : 121
    Points
    121
    Par défaut
    Citation Envoyé par Waldar Voir le message
    Ok, par contre que ça ne vous empêche pas de réfléchir, dans ce cas il suffit d'inverser la solution :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     SELECT p.id_produit, p.quantite, COALESCE(MIN(t.prix), 0) AS prix
        FROM panier AS p
             LEFT OUTER JOIN tarifs AS t
               ON t.id_produit = p.id_produit
              AND t.quantite  <= p.quantite
    GROUP BY p.id_produit, p.quantite
    C'est justement ce que j'ai tenté au début mais le résultat était prévisible, c'est la première lignes de tarifs qui est retournée => "10.00"

  9. #9
    Membre régulier
    Homme Profil pro
    Développeur Web
    Inscrit en
    Septembre 2005
    Messages
    197
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Ille et Vilaine (Bretagne)

    Informations professionnelles :
    Activité : Développeur Web
    Secteur : Services à domicile

    Informations forums :
    Inscription : Septembre 2005
    Messages : 197
    Points : 121
    Points
    121
    Par défaut
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    CREATE VIEW V_TARIF
    AS
    SELECT id_produit, quantite AS quantie_min,
           COALESCE((SELECT MIN(quantite) - 1
                     FROM   T_TARIF
                     WHERE  quantite > T.quantite), 2000000000) AS quantite_max,
           prix 
    FROM   T_TARIF AS T
    Merci pour cette idée de bosser directement sur une vue, c'est ce que je vais faire par conter je n'ai pas précisé que j'utilise mysql et la requête de création de vue fonctionne mais un select me retourne ceci :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    id_produit  quantie_min quantite_max prix
    ----------- ----------- ------------ ----------
    1           1           1            10.00
    1           5           9            8.00
    1           10          14           6.00
    1           15          19           4.00

  10. #10
    Rédacteur

    Avatar de SQLpro
    Homme Profil pro
    Expert bases de données / SQL / MS SQL Server / Postgresql
    Inscrit en
    Mai 2002
    Messages
    21 768
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Var (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Expert bases de données / SQL / MS SQL Server / Postgresql
    Secteur : Conseil

    Informations forums :
    Inscription : Mai 2002
    Messages : 21 768
    Points : 52 719
    Points
    52 719
    Billets dans le blog
    5
    Par défaut
    MySQL n'est pas un SGBD Relationnel. C'est un ersatz. En fait un gestionnaire de fichiers avec une surcouche de SQL qui donne des résultats fantaisistes... En effet MySQL ne sait pas gérer les NULL, d'où des résultats de requête faux !

    Utilisez un vrai SGBDR et abandonnez MySQL si vous voulez vraiment faire du SGBD relationnel !

    A lire sur le sujet : http://blog.developpez.com/sqlpro/p9...udre-aux-yeux/

    A +
    Frédéric Brouard - SQLpro - ARCHITECTE DE DONNÉES - expert SGBDR et langage SQL
    Le site sur les SGBD relationnels et le langage SQL: http://sqlpro.developpez.com/
    Blog SQL, SQL Server, SGBDR : http://blog.developpez.com/sqlpro
    Expert Microsoft SQL Server - M.V.P. (Most valuable Professional) MS Corp.
    Entreprise SQL SPOT : modélisation, conseils, audit, optimisation, formation...
    * * * * * Expertise SQL Server : http://mssqlserver.fr/ * * * * *

  11. #11
    Membre régulier
    Homme Profil pro
    Développeur Web
    Inscrit en
    Septembre 2005
    Messages
    197
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Ille et Vilaine (Bretagne)

    Informations professionnelles :
    Activité : Développeur Web
    Secteur : Services à domicile

    Informations forums :
    Inscription : Septembre 2005
    Messages : 197
    Points : 121
    Points
    121
    Par défaut
    Oui ok c'est bien tout ça mais je n'ai pas la possibilité de changer donc je fais avec ce que j'ai.

  12. #12
    Modérateur
    Avatar de Waldar
    Homme Profil pro
    Customer Success Manager @Vertica
    Inscrit en
    Septembre 2008
    Messages
    8 452
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 46
    Localisation : France, Val de Marne (Île de France)

    Informations professionnelles :
    Activité : Customer Success Manager @Vertica
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2008
    Messages : 8 452
    Points : 17 820
    Points
    17 820
    Par défaut
    Citation Envoyé par Shiva Voir le message
    C'est justement ce que j'ai tenté au début mais le résultat était prévisible, c'est la première lignes de tarifs qui est retournée => "10.00"
    Vous avez du faire une erreur en essayant, car avec des données (j'ai construit le test sur SQL-Server) :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    With panier (id_produit, quantite) as
    (
    select 1, 6
    )
      ,  tarifs (id_produit, prix, quantite) as
    (
    select 1, 10,  1 union all
    select 1,  8,  5 union all
    select 1,  6, 10 union all
    select 1,  4, 15
    )
     SELECT p.id_produit, p.quantite, COALESCE(MIN(t.prix), 0) AS prix
        FROM panier AS p
             LEFT OUTER JOIN tarifs AS t
               ON t.id_produit = p.id_produit
              AND t.quantite  <= p.quantite
    GROUP BY p.id_produit, p.quantite
     
    id_produit  quantite    prix
    ----------- ----------- -----------
    1           6           8
    N'oubliez pas que cette requête ne fonctionne que si le prix est toujours dégressif avec l'augmentation de quantité.
    Si ce n'est pas un fait établi (voire contrôlé), il vaut mieux utiliser la vue proposée par SQLPro.

Discussions similaires

  1. Récupérer le bon élément dans un JSON (map() jquery)
    Par WeDgEMasTeR dans le forum jQuery
    Réponses: 4
    Dernier message: 21/05/2013, 11h19
  2. [AC-2000] Requête : appliquer le bon tarif selon la date
    Par kerseb dans le forum Modélisation
    Réponses: 7
    Dernier message: 31/12/2010, 13h18
  3. Comment récupérer le bon Code Erreur par le tray-catch
    Par belaggoun2000 dans le forum C++Builder
    Réponses: 1
    Dernier message: 16/02/2009, 14h03
  4. Réponses: 3
    Dernier message: 18/06/2008, 14h33
  5. Récupérer le bon id dans un getElementById
    Par joss91 dans le forum Général JavaScript
    Réponses: 15
    Dernier message: 14/05/2008, 20h30

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo