PHP|Débutant :: Forums

Advertisement

Besoin d'aide ? N'hésitez pas, mais respectez les règles

Vous n'êtes pas identifié(e).

#1 10-07-2010 18:50:05

moijhd
Membre
Inscription : 13-06-2009
Messages : 167

Plusieurs requêtes possibles : meilleurs choix ?

Bonjour,

Ce post est en partie la suite de celui-ci : http://forum.phpdebutant.org/viewtopic.php?pid=63882, mais sa connaissance n'est pas requise pour ce qui suit.

Pour une même action, je peux choisir plusieurs requêtes qui me retournent toutes le même résultat. La question de de savoir laquelle est la meilleure, ou d'en proposer une meilleure.

Il a été établi au poste précédent que la requête suivante permet de dire si l'élève est cotisant ou pas (elle peut toujours être critiquée) :

[code mysql]

                SELECT
                CASE
                    WHEN COUNT(*) >= 1
                    THEN 1
                    ELSE 0
                END as nombre
            FROM
                cotisations
            WHERE
                CASE WHEN CURDATE() < STR_TO_DATE(CONCAT(YEAR(CURDATE()),'0630'),'%Y%m%d')
                    THEN cotisations.date_achat BETWEEN
                            STR_TO_DATE(CONCAT(YEAR(CURDATE())-1,'0701'),'%Y%m%d') AND
                            STR_TO_DATE(CONCAT(YEAR(CURDATE()),'0701'),'%Y%m%d')
                    ELSE cotisations.date_achat BETWEEN
                            STR_TO_DATE(CONCAT(YEAR(CURDATE()),'0701'),'%Y%m%d') AND
                            STR_TO_DATE(CONCAT(YEAR(CURDATE())+1,'0701'),'%Y%m%d')
                END    AND
                cotisations.id_eleve = ".$this->IdEleve."

[/code]

Il s'agit maintenant de déterminer un prix suivant trois facteurs : la cotisation, l'acompte, le paiment.

La table ci-dessous représente les différents cas :

[code mysql]

--
-- Structure de la table `wei_prix`
--

CREATE TABLE IF NOT EXISTS `wei_prix` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `cotisation` tinyint(1) NOT NULL,
  `acompte` tinyint(1) NOT NULL,
  `paye` tinyint(1) NOT NULL,
  `prix` int(3) NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=MyISAM  DEFAULT CHARSET=utf8 AUTO_INCREMENT=9 ;

--
-- Contenu de la table `wei_prix`
--

INSERT INTO `wei_prix` (`id`, `cotisation`, `acompte`, `paye`, `prix`) VALUES
(1, 0, 0, 0, 130),
(2, 0, 0, 1, 0),
(3, 0, 1, 0, 100),
(4, 0, 1, 1, 0),
(5, 1, 0, 0, 100),
(6, 1, 0, 1, 0),
(7, 1, 1, 0, 70),
(8, 1, 1, 1, 0);

[/code]

La table dans laquelle sont enregistrés les champ acompte et paye (cotisation étant obtenu avec la première requête) :

[code mysql]

--
-- Structure de la table `wei`
--

CREATE TABLE IF NOT EXISTS `wei` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `id_eleve` int(11) NOT NULL,
  `bus` int(1) NOT NULL DEFAULT '0',
  `acompte` int(1) NOT NULL DEFAULT '0',
  `paye` int(1) NOT NULL DEFAULT '0',
  `date_acompte` datetime NOT NULL,
  `date_paye` datetime NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=MyISAM  DEFAULT CHARSET=utf8 AUTO_INCREMENT=6 ;

[/code]

Comment composer la meilleure requête ?

Vous trouverez mes propositions ici : http://forum.phpdebutant.org/viewtopic. … 032#p65032. Cependant, dans ces cas, si l'enregistrement n'existe pas, la requête ne renvoit rien alors que je voudrais qu'elle retourne prix = 130.

Merci !

Dernière modification par moijhd (10-07-2010 18:55:07)

Hors ligne

#2 11-07-2010 09:46:46

Maljuna Kris
Infantimigulo
Lieu : Douarnenez 29100 Breizh Izel
Inscription : 08-05-2009
Messages : 2 453
Site Web

Re : Plusieurs requêtes possibles : meilleurs choix ?

Peux-tu nous expliciter clairement la finalité des colonnes `cotisation`, `acompte` et `paye`de la table `wei_prix` ?


Gloire à qui n'ayant pas d'idéal sacro-saint,
Se borne à ne pas trop emmerder ses voisins. G. Brassens Don Juan 1976.
Avĉjo MoKo kantas
La chaîne YouTube MoKo Papy

Hors ligne

#3 11-07-2010 10:01:34

moijhd
Membre
Inscription : 13-06-2009
Messages : 167

Re : Plusieurs requêtes possibles : meilleurs choix ?

Des booleens.  Si il y a cotisation et acompte alors le prix est 70 (cas 7).

Cette table n'est pas forcément à utiliser. Elle représente les différents prix suivant la valeur des booleens cotisation, acompte et paye.

Hors ligne

#4 11-07-2010 10:21:12

Jc
Membre
Lieu : Zillisheim - Alsace
Inscription : 15-04-2010
Messages : 1 629
Site Web

Re : Plusieurs requêtes possibles : meilleurs choix ?

Bonjour,

Juste une info concernant l'utilisation de TINYINT comme valeur booléenne. Sur le principe cela fonctionne au niveau mysql tant sur une clause where ou update (set status=false  / set status=true / respectivement 0 et 1 sur mySQL) mais le souci est qu'une telle colonne autorise l'attribution d'autres valeurs que 0 et 1 et que cela peut poser des problèmes de traitement. Sans parler des languages de prog qui considèrent que false=-1 et qui à ce moment là n'est plus gérable niveau requête. Il vaut mieux passer par une définition de champ à mon sens telle que 'T' et 'F' sur un champ ENUM qui rends possible les traitements quels que soient les languages de programmation utilisés et qui protège tes données si une valeur incorrecte de champ est tentée d'être passée via une requête bugée.

PS: si tu ne veux pas passer par un champ de type enum, la seule possibilité est de définir un champ de type BOOL dont TINYINT(1) est l'équivalent et non int(1).

Dernière modification par Jc (11-07-2010 10:45:08)


POO PHP+Ajax en MVC avec PDO et Bases de données épaisses  : What else?

Hors ligne

#5 11-07-2010 10:33:36

Jc
Membre
Lieu : Zillisheim - Alsace
Inscription : 15-04-2010
Messages : 1 629
Site Web

Re : Plusieurs requêtes possibles : meilleurs choix ?

Re,

Un petit conseil aussi dans ta vision de définition de requête. Tu n'as pas forcément besoin que ta requête te donne le montant du prix pour savoir si il y a eu cotisation et/ou accompte d'autant que dans ta dernière requete tu lui demandes de retourner qu'un seul enregistrement car tu fais une recherche sur ta clé primaire id_eleve=x . Dans ce cas particulier ta clause where case... est obsolète car elle n'aurait d'intérêt que dans le but de filtrer l'ensemble du fichier disponible. De plus dans ce dernier cas, ce genre de filtre en production n'est généralement utilisé que pour générer des alertes client au niveau des consoles d'administration (relances, rappels, ...). Donc ces alertes se font à chaque fois sur un seul critère (cotisation ou accompte).
A moins que ton ton rendu souhaité soit purement un exercice de style théorique, je pense que de recadrer tes requêtes dans un contexte d'exploitation te permettrais une meilleure opti et donc une simplification de tes requêtes.

voilou smile

Dernière modification par Jc (11-07-2010 10:39:21)


POO PHP+Ajax en MVC avec PDO et Bases de données épaisses  : What else?

Hors ligne

#6 11-07-2010 10:45:08

moijhd
Membre
Inscription : 13-06-2009
Messages : 167

Re : Plusieurs requêtes possibles : meilleurs choix ?

Disons que j'aime beaucoup l'exercice théorique tongue

Revenons à cette requête qui est la version naive du problème (d'après moi...) :

[code mysql]
SELECT
    CASE WHEN COUNT(*) = 0
        THEN 130
        ELSE
            CASE WHEN wei.paye = true
                THEN
                    0
                ELSE
                    130
                    -
                    (
                        CASE WHEN wei.acompte = true
                            THEN
                                30
                            ELSE
                                0
                        END
                    )
                    -
                    (
                        SELECT
                            CASE
                                WHEN COUNT(*) >= 1
                                THEN 30
                                ELSE 0
                            END as nombre
                        FROM
                            cotisations
           
                        WHERE
                            CASE WHEN CURDATE() < STR_TO_DATE(CONCAT(YEAR(CURDATE()),'0630'),'%Y%m%d')
                                THEN cotisations.date_achat BETWEEN
                                        STR_TO_DATE(CONCAT(YEAR(CURDATE())-1,'0701'),'%Y%m%d') AND
                                        STR_TO_DATE(CONCAT(YEAR(CURDATE()),'0701'),'%Y%m%d')
                                ELSE cotisations.date_achat BETWEEN
                                        STR_TO_DATE(CONCAT(YEAR(CURDATE()),'0701'),'%Y%m%d') AND
                                        STR_TO_DATE(CONCAT(YEAR(CURDATE())+1,'0701'),'%Y%m%d')
                            END    AND
                            cotisations.id_eleve = wei.id_eleve
                    )
            END
    END AS prix
FROM
    wei
WHERE
    wei.id_eleve = ".$this->IdEleve."

[/code]

Dernière modification par moijhd (11-07-2010 10:57:15)

Hors ligne

#7 11-07-2010 10:50:33

Jc
Membre
Lieu : Zillisheim - Alsace
Inscription : 15-04-2010
Messages : 1 629
Site Web

Re : Plusieurs requêtes possibles : meilleurs choix ?

Tout d'abord, tu dois privilégier le tri sur la clé primaire si tu as besoin de recup l'info sur la personne considérée. Tu déclares ensuite les champs cotisation, accompte, paye dans ta clause select et concernant la valeur de prix tu le calcule en fonction des précédents via une clause case. La seule condition que l'on doit trouver dans ta clause where dans ce cas c'est donc "where id_eleve=x."

Dernière modification par Jc (11-07-2010 10:53:27)


POO PHP+Ajax en MVC avec PDO et Bases de données épaisses  : What else?

Hors ligne

#8 11-07-2010 10:54:40

Jc
Membre
Lieu : Zillisheim - Alsace
Inscription : 15-04-2010
Messages : 1 629
Site Web

Re : Plusieurs requêtes possibles : meilleurs choix ?

ah j'oubliais, conformément à mes posts précédents, il ne faut pas écrire wei.accompte=1 mais wei.accompte=true, et idem pour le reste.

PS/EDIT : si tu veux savoir en plus si l'eleve en cours à un abo en cours de validité, tu rajoutes une colonne dans select et tu appliques la même methode sur la colonne que pour ta colonne prix.

Dernière modification par Jc (11-07-2010 11:00:06)


POO PHP+Ajax en MVC avec PDO et Bases de données épaisses  : What else?

Hors ligne

#9 11-07-2010 10:59:58

moijhd
Membre
Inscription : 13-06-2009
Messages : 167

Re : Plusieurs requêtes possibles : meilleurs choix ?

Up sur la dernière requête mise à jour en partie :

http://forum.phpdebutant.org/viewtopic. … 192#p65192

Je fais la recherche sur une personne en particulier.
Je prépare une autre requête avec plus d'opérateur logique.

Hors ligne

#10 11-07-2010 11:09:56

moijhd
Membre
Inscription : 13-06-2009
Messages : 167

Re : Plusieurs requêtes possibles : meilleurs choix ?

EN évitant les deux recherches sur la cotisation (je ne sais pas comment faire...) ?

[code mysql]
SELECT
    CASE WHEN COUNT(*) = 0
        THEN 130
        ELSE
            CASE WHEN wei.paye = true
                THEN
                    0
                ELSE
                    CASE WHEN
                        wei.acompte XOR
                        (
                            SELECT
                                CASE
                                    WHEN COUNT(*) >= 1
                                    THEN true
                                    ELSE false
                                END as nombre
                            FROM
                                cotisations
                            WHERE
                                CASE WHEN CURDATE() < STR_TO_DATE(CONCAT(YEAR(CURDATE()),'0630'),'%Y%m%d')
                                    THEN cotisations.date_achat BETWEEN
                                            STR_TO_DATE(CONCAT(YEAR(CURDATE())-1,'0701'),'%Y%m%d') AND
                                            STR_TO_DATE(CONCAT(YEAR(CURDATE()),'0701'),'%Y%m%d')
                                    ELSE cotisations.date_achat BETWEEN
                                            STR_TO_DATE(CONCAT(YEAR(CURDATE()),'0701'),'%Y%m%d') AND
                                            STR_TO_DATE(CONCAT(YEAR(CURDATE())+1,'0701'),'%Y%m%d')
                                END    AND
                                cotisations.id_eleve = wei.id_eleve
                        )
                        THEN 100
                        ELSE
                            CASE WHEN
                                wei.acompte AND
                                (
                                    SELECT
                                        CASE
                                            WHEN COUNT(*) >= 1
                                            THEN true
                                            ELSE false
                                        END as nombre
                                    FROM
                                        cotisations
                                    WHERE
                                        CASE WHEN CURDATE() < STR_TO_DATE(CONCAT(YEAR(CURDATE()),'0630'),'%Y%m%d')
                                            THEN cotisations.date_achat BETWEEN
                                                    STR_TO_DATE(CONCAT(YEAR(CURDATE())-1,'0701'),'%Y%m%d') AND
                                                    STR_TO_DATE(CONCAT(YEAR(CURDATE()),'0701'),'%Y%m%d')
                                            ELSE cotisations.date_achat BETWEEN
                                                    STR_TO_DATE(CONCAT(YEAR(CURDATE()),'0701'),'%Y%m%d') AND
                                                    STR_TO_DATE(CONCAT(YEAR(CURDATE())+1,'0701'),'%Y%m%d')
                                        END    AND
                                        cotisations.id_eleve = wei.id_eleve
                                )
                                THEN 70
                                ELSE 130
                            END
                    END
            END
    END AS prix
FROM
    wei
WHERE
    wei.id_eleve = ".$this->IdEleve."
[/code]

Dernière modification par moijhd (11-07-2010 11:10:44)

Hors ligne

#11 11-07-2010 11:14:20

Maljuna Kris
Infantimigulo
Lieu : Douarnenez 29100 Breizh Izel
Inscription : 08-05-2009
Messages : 2 453
Site Web

Re : Plusieurs requêtes possibles : meilleurs choix ?

Il s'agit maintenant de déterminer un prix suivant trois facteurs : la cotisation, l'acompte, le paiment.

Rappel de cette table de vérité :

`cotisation`  F     F    F     F    V     V   V   V
`acompte`     F     F    V     V    F     F   V   V
`paye`        F     V    F     V    F     V   F   V
`prix`        130   0    100   0    100   0   70  0

Il suffirait maintenant de faire une jointure entre la table wei et la table wei_prix dont la clause ON vérifierait la correspondance entre les colonnes `acompte`et `paye` ainsi que l'adéquation entre `cotisation` et  la première requête.


Gloire à qui n'ayant pas d'idéal sacro-saint,
Se borne à ne pas trop emmerder ses voisins. G. Brassens Don Juan 1976.
Avĉjo MoKo kantas
La chaîne YouTube MoKo Papy

Hors ligne

#12 11-07-2010 11:20:52

moijhd
Membre
Inscription : 13-06-2009
Messages : 167

Re : Plusieurs requêtes possibles : meilleurs choix ?

?

[code mysql]
SELECT
    CASE WHEN COUNT(*) = 0
        THEN
            130
        ELSE
            wei_prix.prix
    END AS prix
FROM
    wei_prix
INNER JOIN
    wei ON
        wei_prix.acompte = wei.acompte AND
        wei_prix.paye = wei.paye AND
        wei_prix.cotisation = (
            SELECT
                CASE
                    WHEN COUNT(*) >= 1
                    THEN true
                    ELSE false
                END as nombre
            FROM
                cotisations
            WHERE
                CASE WHEN CURDATE() < STR_TO_DATE(CONCAT(YEAR(CURDATE()),'0630'),'%Y%m%d')
                    THEN cotisations.date_achat BETWEEN
                            STR_TO_DATE(CONCAT(YEAR(CURDATE())-1,'0701'),'%Y%m%d') AND
                            STR_TO_DATE(CONCAT(YEAR(CURDATE()),'0701'),'%Y%m%d')
                    ELSE cotisations.date_achat BETWEEN
                            STR_TO_DATE(CONCAT(YEAR(CURDATE()),'0701'),'%Y%m%d') AND
                            STR_TO_DATE(CONCAT(YEAR(CURDATE())+1,'0701'),'%Y%m%d')
                END    AND
                cotisations.id_eleve = wei.id_eleve       
            )
WHERE
    wei.id_eleve = ".$this->IdEleve."[/code]

Dernière modification par moijhd (11-07-2010 11:38:11)

Hors ligne

#13 11-07-2010 13:12:34

Maljuna Kris
Infantimigulo
Lieu : Douarnenez 29100 Breizh Izel
Inscription : 08-05-2009
Messages : 2 453
Site Web

Re : Plusieurs requêtes possibles : meilleurs choix ?

Je crois que tu la tiens.


Gloire à qui n'ayant pas d'idéal sacro-saint,
Se borne à ne pas trop emmerder ses voisins. G. Brassens Don Juan 1976.
Avĉjo MoKo kantas
La chaîne YouTube MoKo Papy

Hors ligne

#14 11-07-2010 17:23:36

Pierrot
Ancien nouveau
Inscription : 08-05-2009
Messages : 1 195

Re : Plusieurs requêtes possibles : meilleurs choix ?

je dois venir d'un autre monde sad
j'entrave ketchick sad:(:
a++

Hors ligne

#15 11-07-2010 18:26:33

moijhd
Membre
Inscription : 13-06-2009
Messages : 167

Re : Plusieurs requêtes possibles : meilleurs choix ?

Ma question dans ce post était de savoir qu'elle était la meilleure méthode : c'est donc celle qui consiste à passer par une table intermédiaire (ma table logique) ? Par rapport à mes soustractions successives ? Par rapport à mes select imbriqués ?

Je pose beaucoup de questions : ce sont mes premières requêtes un peu complexe.

Dernière modification par moijhd (11-07-2010 18:28:42)

Hors ligne

#16 11-07-2010 19:32:10

Maljuna Kris
Infantimigulo
Lieu : Douarnenez 29100 Breizh Izel
Inscription : 08-05-2009
Messages : 2 453
Site Web

Re : Plusieurs requêtes possibles : meilleurs choix ?

D'après toi ?


Gloire à qui n'ayant pas d'idéal sacro-saint,
Se borne à ne pas trop emmerder ses voisins. G. Brassens Don Juan 1976.
Avĉjo MoKo kantas
La chaîne YouTube MoKo Papy

Hors ligne

#17 11-07-2010 21:27:22

moijhd
Membre
Inscription : 13-06-2009
Messages : 167

Re : Plusieurs requêtes possibles : meilleurs choix ?

Et bien, cette structure me permet de bien gérer les données (en particulier les prix), je peux assez facilement la changer si je dois faire évoluer les cas. La requête est assez bien lisible. Je ne sais pas si ce sont les bons arguments pour cette méthode !

Merci !

Et a bientôt pour une nouvelle requête ^^

Hors ligne

#18 11-07-2010 23:46:22

Jc
Membre
Lieu : Zillisheim - Alsace
Inscription : 15-04-2010
Messages : 1 629
Site Web

Re : Plusieurs requêtes possibles : meilleurs choix ?

Bonsoir,

parfois je me demande si les réponses aux questions sont prises en considération ou si celui qui pose la question fait l'effort de comprendre les réponses. Visiblement vu la dernière réponse de ce post, ca n'a pas l'air de poser de problèmes^^.

Bonne continuation à toi dans ta recherche de requêtes^^.


POO PHP+Ajax en MVC avec PDO et Bases de données épaisses  : What else?

Hors ligne

Pied de page des forums