Vous n'êtes pas identifié(e).
Bonjour,
J'ai essayer de faire un titre clair, mais pas sur que ce soit le cas ^^
En fait, j'ai besoin de faire une requete qui me permet d'afficher les factures qui n'ont pas été payées (ou pas complètement).
J'ai une table facture qui contient entre autre le montant que le client a deja payé.
Le prix de la facture n'existe pas tel quel. Il est obtenu a partir de la somme des cout des prestations lié a la facture (chaque prestation est dans la table prestation).
L'idée pour afficher les factures non payées est donc de comparer le prix payés par le client aux totales des couts des prestation.
Est ce que l'on peut faire ca en 1 requetes?
Voila ce que j'ai essayer de faire, tout en sachant que ca ne fonctionnerait pas...
Merci pour vos idées
Hors ligne
Saluton,
Bon, tu y étais "presque".
Tu conviendras aisément avec moi qu'une facture sans client n'a pas de raison d'être, donc la jointure externe vers la table fact_client doit être remplacée par une jointure interne.
Mais ce n'est pas ce qui empêche ta requête d'aboutir.
prixfacture est le résultat d'une fonction d'agrégation SUM dont le résultat ne peut être inféré dans la clause WHERE mais seulement après le GROUP BY.
Pour ce faire il existe une clause HAVING.
Ça devrait aller mieux comme cela.
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
Ah oui c'est vrai, le having
Je ne l'utilise jamais (a tort peut etre)
Merci je vais tester ca (et merci pr les petites astuces/infos)
Hors ligne
Je reviens avec une autre question sur une requete similaire :
La requete fonctionne bien, cependant, j'aimerais afficher que les résultats qui pour date "date_send_fact" et "date_send_doc" vide
Facile me direz vous, mais non, car ces champs sont des la tables fact_suivi et il est possible qu'il n'existe pas... et si il n'y a pas d'enregistrement il ne me les affiches pas (alors que si ils sont vides ou inexistant, pour moi c'est la meme chose)
Une idée svp?
Merci
Yves
Hors ligne
Saluton,
Il faudrait savoir ce qui est prévu comme valeur par défaut dans ces colonnes.
En fait, j'ai besoin de savoir ce qu'elles contiennent lorsqu'elles sont vides.
Il faudrait aussi que tu me dises dans quel(s) cas elles peuvent ne pas exister.
Amike.
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
En fait c'est un table qui permet de faire le suivi d'une facture.
Elle contient des informations comme : date d'envoi de la facture, méthode d'envoi, a qui elle a été envoyé, date d'envoi du doc complémentaire, etc...
L'enregistrement correspondant a une facture n'existe qu'a partir du moment ou le membre a renseigné (via un formulaire) l'une de ses informations (cad qu'il a déja commencer a faire le suivi).
"date_send_fact" et "date_send_doc" sont au format varchar(10).
DOnc en faite, ce que je veux faire, c'est afficher un tableau qui contient les informations suivante :
numéro de facture, la date d'envoie de la facture, la date de payement (contenu dans la table facture donc pas de soucis) et la date d'envoi du doc
Mais si les 3 champs date contiennent qqchose (ce qui veut donc dire que le suivi est complet), il n'est pas necessaire d'afficher la ligne de la facture.
Est ce que je suis plus clair?
Merci
Hors ligne
bonjour,
permet moi de reformuler ton besoin histoire dêtre certain d'avoir bien compris tu as besoin d'afficher les factures initiées non payées et/ou les factures dont le doc n'a pas été envoyé.
Si c'est bien ça et si il ne peut y avoir de doc envoyé tant qu'elle n'est pas payée dans les procédures de l'entreprise concernée, il suffit de faire le test sur la date d'envoi du doc. Si la date est NULL et que la date d'envoi est NOT NULL, alors on affiche.
J'espère avoir pu t'aider.
++
POO PHP+Ajax en MVC avec PDO et Bases de données épaisses : What else?
Hors ligne
Humm tu me donnes des idées, faudrait tester.
Mais ce que je voulais faire, c'est lister toutes les factures pour lesquelles une ou plusieurs étapes n'avaient pas été faite et donc avoir une requete du genre :
Mais si la facture n'a pas d'enregistrement dans la table fact_suivi, ca ne me ressort rien du coup..
Hors ligne
Mais si la facture n'a pas d'enregistrement dans la table fact_suivi, ca ne me ressort rien du coup..
Avec les jointures externes (LEFT JOIN) qui partent de la table facture, tu dois récupérer toutes les factures, qu'elles aient ou non d'enregistrement dans la table fact-suivi.
Si ce n'est pas le cas c'est que tes clauses WHERE ou HAVING sont trop restrictives.
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
c'est lister toutes les factures pour lesquelles une ou plusieurs étapes n'avaient pas été faite
On en revient toujours au même, quand on est laxiste sur les processes d'entreprise, on en revient à perdre la consistence des données de l'entreprise, et c'est le début de la fin.
Les CMS ont encore de beaux jours devant eux, moi je vous l'dit !!!
POO PHP+Ajax en MVC avec PDO et Bases de données épaisses : What else?
Hors ligne
Bonsoir
Je reviens avec ma requête fini.. enfin je croyais
Elle fonctionne, pas d'erreur, mais les valeurs obtenu pour prixFacture ne sont pas correctes.
Voici la requête :
J'ai des valeurs bizarre (et pour le moment inexpliqué) pour prixFacture.
Si je simplifie la requête a ça, je n'ai plus de soucis :
Mais ce n'est pas ce que j'ai besoin... une idée de ce qu'il se passe? On dirait que la requete boucle ce qui fait grimper la valeur de prixFacture
Merci pour votre aide
Yves
Dernière modification par ebouilleur (12-12-2012 21:06:00)
Hors ligne
Bonjour,
La première chose que j'allais te dire après avoir lu tes requêtes c'est qu'on a déjà évoqué ce problème dans ton premier post sur ce forum à savoir qu'il faut remettre la fonction d'agrégation dans le HAVING pour prixFacture au lieu de son alias. Mais lorsque tu dis
"On dirait que la requête boucle ce qui fait grimper la valeur de prixFacture", je ne suis plus certain de la nature de ton problème en fait.
Tu pourrais nous dire ce que tu obtiens concrètement et ce que tu devrais obtenir sur 1 ou 2 lignes d'exemple ?
De plus ton HAVING dans ta première requête ne corresponds pas au cahier des charges de ta requête.
10.HAVING f.montant_paye<prixFacture OR date_send_fact IS NULL OR date_send_doc IS NULL
En effet
1) f.montant_paye < prixFacture n'exclue pas le montant_paye =0 ce qui sort du contexte souhaité
2) le OR appliqué à la fois sur date_send_fact IS NULL OR date_send_doc IS_NULL non seulement n'exclue pas f.montant_paye=0 mais même si montant_paye=0 a été exclu dans la première condition, cette partie la rendrait à nouveau inclusive.
3) il te faudrait plutôt un
Tu remarqueras aussi le inférieur ou égal car la facture soldée rentre aussi dans le CDC que tu as exprimé, et normalement en n'oubliant pas de remplacer l'alias par la fonction d'agrégation.
Merci
Dernière modification par Jc (13-12-2012 05:26:52)
POO PHP+Ajax en MVC avec PDO et Bases de données épaisses : What else?
Hors ligne
Salut,
Dans mon 1er post, Kris me disait juste de mettre f.montant_paye <= prixFacture dans le having à la place du where, mais il ne me disait pas de mettre SUM( (p.prix_htva + ( (p.prix_htva * p.tva) /100 ) ) * p.quantite) à la place de prixFacture, enfin si j'ai bien compris.
Donc ça donnerai la requête suivante :
Pour mon having, j'ai du mal a comprendre ta proposition, car j'ai besoin de voir toutes les factures dont au moins 1 des 3 actions (payement, envoie de facture et envoie de doc) ne sont pas effectuées. Donc si le client n'a rien payé, ça doit être listé alors que si je met (f.montant_paye >0 AND f.montant_paye <= prixFacture) ca ne listera rien, non?
Pour visualisé un peu mon tableau d'affichage, ca donne qqchose du genre :
Facture Payé Facture envoyé Doc envoyé
31 OK OK NOK
13 OK NOK NOK
58 NOK NOK NOK
Sinon voici une exemple de résultat de la requête actuelle :
id_facture montant_paye prixFacture date_send_fact date_send_doc
31 716.00 2860.260920000000 2012-12-09 2012-12-09
13 12.00 7.260000000000 2012-12-01 NULL
Et ce que je devrais avoir :
31 716.00 715.065230000000 2012-12-09 2012-12-09
13 12.00 2.420000000000 2012-12-01 NULL
Voila,
Merci
Hors ligne
Bonsoir,
Je vais faire un petit rappel pour aide mémoire.
Quand le moteur de base de données doit parser la requête, il faut savoir que la clause SELECT est évaluée en dernier, et donc après les clauses FROM, WHERE, GROUP BY et HAVING (dans l'ordre). Ainsi les alias définis dans la clause SELECT sont inconnus au moment de l'évaluation des mêmes clauses.
Ensuite pour les alias je te recommande d'utiliser le mot clé AS systématiquement, car c'est une source d'erreur fréquente et difficile à déboguer surtout dans les requêtes complexes
Imagine par exemple que tu oublies une simple virgule en écrivant SELECT order_id order_date FROM orders ne retournera pas d'erreur mais order_date sera considéré comme un alias de order_id et donc une seule colonne sera affichée.
En plus je n'ai pas vérifié mais je crois que MySQL ne supporte pas l'absence de mot clé AS (l'ayant toujours mis en fait).
Pour ce qui est de l'obligation de répéter des formules un peu longues dans les clauses WHERE et HAVING, elles sont reconnues par l'optimiseur et sont évaluées qu'une seule fois contrairement à ce que l'on pourrait penser. Du moins sur SQL Server c'est certain à 100%, j'ai pas vérifié dans la doc MySQL^^.
Si tu veux éviter de te retaper 10 fois le calcul à la main dans ta requête, la solution peut être de créer une requête dérivée intégrant les calculs, ainsi il est possible d'y faire référence à l'extérieur via un alias (la clause FROM étant évaluée en premier).
Pour ton problème d'expression dans ton HAVING, excuse moi mais ton besoin précis ne m'apparaît pas clairement
Dernière modification par Jc (22-06-2013 17:18:47)
POO PHP+Ajax en MVC avec PDO et Bases de données épaisses : What else?
Hors ligne
Merci pour ton aide mémoire
Pour le AS c'est vrai que je le met quasiment toujours, même si là je l'ai oublié pour les tables. Sinon, si mysql gère aussi quand tu ne met pas le AS, mais j'aime bien le mettre, c'est plus clair au niveau du code, je suis d'accord.
Donc ca donnerai :
Pour le HAVING et ce que je souhaite, c'est simple pourtant, disons que ce tableau de suivi de facture permet de :
- voir si la facture a été envoyé
- ou voir le le doc a été envoyé
- ou voir si la facture a été payé
Mais que ce soit le "problème" de AS ou de Having, le résultat de prixFacture bizarre ne s'explique pas
(pour info j'ai aussi tester ma requête sans le having, et prixFacture est tjs aussi bizarre)
Edit :
Par contre, après d'autres tests, j'ai remarqué que si dans ma table fact_suivi, je n'ai aucun enregistrement, ou 1 seul, la valeur de prixFacture sera bonne, et elle devient fausse quand j'ai 2 ou plus d'enregistrement. (pour 2 enregistrement, prixFacture est en fait le double de la valeur qu'il devrait avoir)
Dernière modification par ebouilleur (14-12-2012 10:16:04)
Hors ligne
Oui comme ça je comprends mieux. En fait ton regroupement sur id_facture tu le fais sur la table fact_facture, alors que cette table n'est censée contenir qu'une seule référence à chaque facture, (ou une référence par paiement ?) si j'ai bien compris.
Tu as deux agrégations à faire, celle du calcul du montant de la facture dans la table fact_suivi qui je pense doit être faite dans une requête dérivée justement, et si tu as qu'une seule référence facture dans fact_facture alors tu reprends la même requête et ca doit être bon, sinon dans le cas où tu as une référence par paiement partiel, tu refais l'agrégation sur le montant payé dans ta requête principale.
Si c'est pas tout à fait ça et que ca ne te suffit pas, donne moi l'analyse fonctionnelle des tables et leur structure ca aidera
Dernière modification par Jc (14-12-2012 15:58:21)
POO PHP+Ajax en MVC avec PDO et Bases de données épaisses : What else?
Hors ligne
Oui la table fact_facture ne contient qu'1 seul enregistrement par facture.
Pour le reste j'ai pas tout compris, donc je colle mes table pour déjà etre sur que tu es sur la bonne voie
CREATE TABLE IF NOT EXISTS `fact_prestation` (
`id_prestation` INT(11) NOT NULL AUTO_INCREMENT,
`id_facture` INT(11) NOT NULL,
`type` tinyint(3) UNSIGNED NOT NULL,
`autre` text NOT NULL,
`date_prestation` DATE NOT NULL,
`adresse` text NOT NULL,
`cp` INT(10) NOT NULL,
`ville` VARCHAR(50) NOT NULL,
`pays` VARCHAR(50) NOT NULL,
`quantite` DECIMAL(6,4) NOT NULL,
`prix_htva` DECIMAL(10,4) NOT NULL,
`tva` tinyint(4) NOT NULL,
UNIQUE KEY `id_prestation` (`id_prestation`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1 AUTO_INCREMENT=11 ;
CREATE TABLE IF NOT EXISTS `fact_suivi` (
`id_suivi` INT(10) UNSIGNED NOT NULL AUTO_INCREMENT,
`id_facture` INT(10) UNSIGNED NOT NULL,
`date_send` VARCHAR(10) NOT NULL,
`who_send` VARCHAR(50) NOT NULL,
`how_send` VARCHAR(50) NOT NULL,
`type` tinyint(3) UNSIGNED NOT NULL,
UNIQUE KEY `id_suivi` (`id_suivi`),
KEY `id_facture` (`id_facture`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1 AUTO_INCREMENT=29 ;
voilà...
Hors ligne
Essaye ça pour voir.
PS: Encore une BD qui a été modélisée à l'arrache
Dernière modification par Jc (15-12-2012 00:29:26)
POO PHP+Ajax en MVC avec PDO et Bases de données épaisses : What else?
Hors ligne
Ah... ca te plait pas comme bdd? qu'est ce qui te convient pas? qu'est ce qui doit être amélioré?
La requete telle qu'elle ne passe pas, il ne connais pas date_send_fact et date_send_doc dans le where. En remplacant le where par un having, ca passe sans erreur, mais ca ne ressort qu'une ligne... je fais des tests, mais j'arrive pas a adapté ta requête pour qu'elle ressorte ce que j'ai besoin, je continu
Dernière modification par ebouilleur (14-12-2012 23:23:26)
Hors ligne
La ligne unique venait du MAX...
Mais du coup, en essayant de comprendre la pertinence de ton MAX, je pense qu'il va falloir faire une requête dérivée au niveau du suivi pour retomber sur nos pattes car cela sous entend qu'il y a plusieurs suivis pour une même facture avec des dates d'envoi différentes... D'où l'ajout ici du ORDER BY, mais cela ne suffira pas.
En plus tes CASE... WHEN sont peu pertinents un simple date_send suffit avec l'information du type pour gérer l'affichage.
sera plus pertinent et plus performant, sutout en MyISAM...
Dernière modification par Jc (15-12-2012 00:43:18)
POO PHP+Ajax en MVC avec PDO et Bases de données épaisses : What else?
Hors ligne
Oui il y a avoir plusieurs enregistrement dans la table suivi pour la meme facture (en principe quand c tout bien fait il y a a minimum 2 ligne : 1 facture et 1 doc). Si il y a 4 envoie de doc, c'est comme si il y en avait que 1 seul. 1 ou plus c'est quand meme 1 ^^
Humm j'ai du mal a saisir ta 2eme requete. Il est possible que le MAX n'était pas très utile, mais la impossible d'avoir l'information de la date d'envoie de ma facture (s1.type=1) et en meme temps la date d'envoie du doc (s1.type=2)
J'en profite pour te glisser le code d'affichage du résultat de la requete :
je vais au lit
Bye
Hors ligne
Bonsoir,
Avant de te répondre sur ton dernier post, je vais te répondre concernant ta base de données
- Elle n'est pas normalisée 3FN minimum
- Elle est en MyISAM et donc les contraintes de clé étrangères sont inopérantes et les performances ne seront pas au rendez-vous, surtout que des indexs ont été oubliés de manière à les rendre efficaces et d'autant plus en MyISAM.
- Tes contraintes de domaine ne sont pas standardisées, ainsi on se retrouve par exemple avec un id_facture sur fact_facture défini en INT UNSIGNED NOT NULL et un id_facture en INT NOT NULL sur fact_prestation, rendant ainsi les jointures inopérantes (fulls scans en perspective), date en VARCHAR, etc...
Sinon c'est bien ce qu'il me semblait il va falloir passer par des requêtes dérivées pour gérer tes dates. Dis-moi, tu as un seul enregistrement par facture et par type de suivi dans la table fact_suivi? Je te pose la question quand même, car normalement la réponse devrait être non si ton MAX était pertinent, mais n'ayant aucune certitude...
Dernière modification par Jc (15-12-2012 01:24:55)
POO PHP+Ajax en MVC avec PDO et Bases de données épaisses : What else?
Hors ligne
Oula, il y a des termes que je lis pour la 1ere fois je vais aller me documenter un peu...
Et pour ta question :
- dans la table fact_facture : OUI 1 seul enregistrement par facture
- dans la table fact_suivi : NON, pas toujours. En principe il doit y avoir au minimum 2 enregistrements (1 pour la facture et 1 pour le doc), mais il est possible (dans 20% des cas) de trouver plusieurs ligne pour le doc (ou la facture) si celui-ci a été envoyé plusieurs fois (pour plusieurs personne par exemple)
Merci
Hors ligne
Bonjour,
C'est bien ce qui me semblait.
Tu es victime pour ta requête de ton absence de modélisation correcte car ta table suivi est redondante donc dénormalisée. Il ne faut pas confondre la gestion des statuts de tes factures, et la gestion des logs action sur les factures émises. Dans ta modélisation actuelle donc, quel est le critère qui doit être retenu en interne pour dire parmi x dates d'envoi quel est la date qui doit être considérée comme étant la date d'envoi officielle pour la facture? Si c'est la dernière, ton MAX est justifié, si c'est la première, ton MAX est faux. Si en interne il suffit de vérifier qu'une date d'envoi existe pour dire qu'elle a été envoyée, alors tu peux t'en sortir avec ta modélisation actuelle et adapter ta requête en conséquence. Sinon tu es dans une impasse fonctionnelle, sauf si c'est l'envoi à une personne particulière qui donne date certaine à l'envoi de la facture.
Bon week-end.
Dernière modification par Jc (15-12-2012 18:16:10)
POO PHP+Ajax en MVC avec PDO et Bases de données épaisses : What else?
Hors ligne
Oula, il y a des termes que je lis pour la 1ere fois hmm je vais aller me documenter un peu...
Ah bon? il me semble pourtant que MK dans un autre post t'as répondu ceci
Étant moi-même assez partisan des SGBD "épais" je t'engage à favoriser la résolution de ce type de problème plutôt en amont de PHP.
Cela sous-entend, bien-entendu, d'avoir optimisé la base de données (choix des types de colonnes, des index, modélisation au plus près des formes normales, contraintes d'intégrité, etc...)
et que rien dans ta réaction ne semblait laisser penser que se sont des notions qui t'étaient étrangères
Dernière modification par Jc (15-12-2012 18:32:24)
POO PHP+Ajax en MVC avec PDO et Bases de données épaisses : What else?
Hors ligne