problème de mode MySQL

Répondre


Cette question est un moyen d’empêcher des soumissions automatisées de formulaires par des robots.
Smileys
:D :) :( :o :shock: :? 8-) :lol: :x :P :oops: :cry: :evil: :twisted: :roll: :wink: :!: :?: :idea: :arrow: :| :mrgreen: =D> #-o =P~ :^o :non: :priere: 8-|
Voir plus de smileys
  Revue du sujet
 

  Étendre la vue Revue du sujet : problème de mode MySQL

par iclo » 09 sept. 2007, 20:34

en pratique oui, tu as soit un mois soit une semaine soit un an
mais en théorie, qu'est-ce qui empeche d'avoir un abonnement d'un mois et 3 jours?
Une base de donnée, doit être adaptée à l'usage qu'on doit en faire. (et permettre de suivre les évolutions de cet usage)
Si tu veux pouvoir avoir des durées d'abonnements "exotiques", rien ne t'empêche d'avoir une table:
- idTypeAbonnement
- Unité (mois, jours, année)
- durée.

Qui permettra de facilement calculé une date de fin.
Un select pour récupérer toutes les durées d'un type d'abonnement, une boucle pour les parcourir, et les ajouter sucessivement pour arriver à la date de fin.

Mais honnêtement, je doute que ce genre de durée puisse exister dans la pratique, et que cela soit nécessaire de se casser la tête la dessus.

par Shrell » 09 sept. 2007, 09:19

en pratique oui, tu as soit un mois soit une semaine soit un an
mais en théorie, qu'est-ce qui empeche d'avoir un abonnement d'un mois et 3 jours?

par iclo » 09 sept. 2007, 00:51

Oui, mais une durée, est d'une seule unité: X mois ou Y jours, mais pas X mois + Y jours, non ?

par Shrell » 08 sept. 2007, 22:07

Si tu as besoin de connaitre la date de fin, pourquoi ne pas la calculer une fois pour toute, à partir de la date de début et de la durée ?
C'est justement ce que je fais! lol
Voici la structure (simplifiée) de ma base :

1) abonnements
id_abonnement
duree

2) abonnes
id_abonne

2) abonnes_abonnements
id_abonne
id_abonnement
date_debut
date_fin

Donc comme je l'ai dit plus haut, au moment de la souscription de l'abonnement, je calcule la date de fin d'abonnement en fonction de la durée

Code : Tout sélectionner

date_fin_abonnement = DATE_ADD(DATE_ADD(DATE_ADD(NOW(), INTERVAL DAY(duree) DAY), INTERVAL MONTH(duree) MONTH), INTERVAL YEAR(duree) YEAR)
sauf que maintenant, duree, qui auparavant était un champ de type DATE, ne peut plus contenir de date invalide...
Donc avec des découpages de varchar je devrais pouvoir m'en sortir...

par iclo » 08 sept. 2007, 20:06

Si tu as besoin de connaitre la date de fin, pourquoi ne pas la calculer une fois pour toute, à partir de la date de début et de la durée ? (Il y a toutes fonctions de manipulations de date nécessaire pour faire ça simplement)
Pour te proposer une solution adaptée à ton problème, il faudrait surtout qu'on sache à quoi vont te servir ces données, et donc sous quel formes du devra les récupérer.

Je ne vois pas trop de raisons de passer par des solutions bricolées, source de problèmes, et surtout très difficiles à modifier par après, notamment si on veut ajouter de nouvelles fonctionnalités.
Un bonne solution (pour ne pas dire une solution acceptable) doit permettre une certaine souplesse d'évolution dans le futur. (On voit très souvent des dévellopeurs bloqués avec des bases de données bancales, dans l'obligation de modifier de gros volumes de données, suite à une erreur de conception antérieure)

par Shrell » 08 sept. 2007, 19:37

La durée est en mois, ou en année, ou en jours (offre promotionnelle d'une semaine par exemple)
J'aurais effectivement la possibilité de stocker dans trois champs différents la durée en années, mois et jours, mais disons qu'avant que ce probleme ne se pose, je trouvais que le fait de stocker ces durées sous un format YYYY-MM-DD était non seulement pratique mais me semblait en plus logique...
Après, j'ai peut etre une logique toute personnelle :lol:
Enfin apparemment il va falloir que je bricole pour arriver au même résultat, j'ai commencé à me faire à l'idée ;)

par iclo » 08 sept. 2007, 18:29

Je dois avouer que je ne comprends pas bien ce que tu dois stocker comme informations, ni pour quel usage:
La durée de tes abonnements est en mois ? si oui pourquoi ne pas stocker cette durée dans un entier ?
Quitte à stocker la date de début, pour pouvoir calculer la date de fin, si nécessaire.

par Shrell » 08 sept. 2007, 15:13

Ce que je veux dire c'est que je ne peux pas prévoir un abonnement différent selon quel jour on s'abonne (je ne sais pas si je me fais bien comprendre :? )
Les abonnements étant (par exemple) du 5/X au 5/Y, selon quels sont X et Y, l'abonnement durera 28, 29, 30 ou 31 jours
Je pense que la solution la plus simple (même si elle ne me plait pas) et de stocker la date en varchar et de la traiter à la main... à moins que quelqu'un sache comment désactiver cette #!@grumpf! de vérification

par ouckileou » 08 sept. 2007, 13:28

@iclo : non, la plus petite unité n'est pas le jour étant donné qu'un abonnement d'un mois pris le 2 février ne fera que 28 jours (voire 29 pour une année bissextile) alors que le même abonnement pris en juillet durera 31 jours...
La plus petite unité est donc le jour :)
Ici, 28 ou 31 unités...

À moins qu'on puisse s'abonner pour moins de 24 heures...

par icebreak » 08 sept. 2007, 03:46

Alors inclus un TIMESTAMP !
Et ça se gèrera facilement avec PHP après.

par Shrell » 07 sept. 2007, 13:40

@iclo : non, la plus petite unité n'est pas le jour étant donné qu'un abonnement d'un mois pris le 2 février ne fera que 28 jours (voire 29 pour une année bissextile) alors que le même abonnement pris en juillet durera 31 jours...

@ripat : bah la date de début d'abonnement, c'est le jour où on s'abonne...
En fait je définis ma table des abonnements (prix, durée, nom...)
Puis au moment où je choisis mon abonnement je fais ceci :
	$requeteverifvalue=mysql_query("SELECT duree_abonnement,id_abonnement,nb_par_pro 
FROM abonnements WHERE id_abonnement=\"".mysql_real_escape_string($_GET['id'])."\"") or exit(mysql_error());
	if(mysql_num_rows($requeteverifvalue) >0) {
		$r=mysql_fetch_assoc($requeteverifvalue);
		$sql="INSERT INTO pros_abonnements 
SET id_pro='".$_SESSION['id_pro']."', id_abonnement='".$r['id_abonnement']."', date_debut_abonnement=NOW(), 
date_fin_abonnement=DATE_ADD(DATE_ADD(DATE_ADD(NOW(), INTERVAL DAY('".$r['duree_abonnement']."') DAY), 
INTERVAL MONTH('".$r['duree_abonnement']."') MONTH), INTERVAL YEAR('".$r['duree_abonnement']."') YEAR)";
        }
J'ai simplifié un peu, mais c'est l'idée
Donc dans ce cas précis, étant donné que $r['duree_abonnement'] n'est pas une date valide, les fonctions DAY(), MONTH() et YEAR() me renvoient NULL, donc les DATE_ADD() s'affolent et le tout plante :(

par Ripat » 07 sept. 2007, 11:58

Tu dois bien avoir une date de début d'abonnement non? Si oui, il te faudra extraire de ta colonne actuelle la durée de l'abonnement et ensuite faire un calcul de fin avec les fonctions MySQL:

Code : Tout sélectionner

SELECT DATE_ADD('2007-09-05', INTERVAL 3 MONTH); SELECT DATE_ADD('2007-09-05', INTERVAL 150 DAY); SELECT DATE_ADD('2007-09-05', INTERVAL 2 YEAR); SELECT DATE_ADD('2007-09-05', INTERVAL 2 WEEK);
Voir http://dev.mysql.com/doc/refman/5.0/fr/ ... n_date-add

La difficulté va être de récupérer les durées sous son ancien format et de les convertir en nombres de DAY MONTH YEAR etc...

Pas impossible. Donne-nous quelques exemple de ces durées pour voir.

par iclo » 07 sept. 2007, 11:37

Si la plus petite unité, est le jour tu peux stocker un nombre de jours.
Maintenant rien ne t'empêche d'utiliser un timestamp (voir la doc pour plus d'infos)

par Shrell » 07 sept. 2007, 11:30

Mouais, sauf que dans l'exemple donné, la durée est de trois mois, mais dans l'enregistrement d'après elle peut etre de 7 jours et dans le suivant d'un an et demi (c'est une table d'abonnements en fait)
Ce que j'ai fait pour l'instant c'est remplacer la date par un varchar et le couper à la main, mais c'est pas beau :(
Donc si d'autres idées passent par ici, je prends :D

par iclo » 07 sept. 2007, 01:48

Deux idées en vrac:
- Changer le type de champs pour utiliser quelques choses de plus naturel : un champ int pour le nombre de mois (en plus ça ferait une économie de place dans la base de donnée)
- Ajouter une année et un jour bidon dans toutes les dates pour qu'elles soient valides (pas très beau comme solution)