php/Mysql - groupage et transfert de données - depuis deux tables, vers une seule

Gallère pour trouver le titre du sujet :smiley:

Alors vla mon soucis :

J’ai des dossiers, et des vehicules contenus dans ces dossiers, avec une clef de liaison entre les deux : idDossier. si vehicules.idDossier égale dossiers.idDossiers, alors mon véhicule appartient à ce dossier :slight_smile:

SQL
CREATE TABLE dossiers (

idDossier int(4) unsigned NOT NULL auto_increment,
codeDossier varchar(15) NOT NULL default ‘’,
Date date NOT NULL default ‘0000-00-00’,
idClient tinyint(3) unsigned NOT NULL default ‘0’,
idTransporteur tinyint(3) unsigned NOT NULL default ‘0’,
Infos text,
MarqueurD tinyint(1) unsigned NOT NULL default ‘3’,
PRIMARY KEY (idDossier),
UNIQUE KEY codeDossier (codeDossier)
) TYPE=MyISAM;

CREATE TABLE vehicules (
idVehicule int(5) unsigned NOT NULL auto_increment,
idDossier tinyint(4) unsigned NOT NULL default ‘0’,
Chassis varchar(17) NOT NULL default ‘’,
Montant decimal(7,2) NOT NULL default ‘0.00’,
Avenant varchar(10) NOT NULL default ‘’,
Details varchar(50) default NULL,
MarqueurV tinyint(1) unsigned NOT NULL default ‘1’,
PRIMARY KEY (idVehicule)
) TYPE=MyISAM;

Je voudrais, dans une nouvelle table (car je pense que c’est la façon la plus propre de faire) consolider ces données pour ensuite faire du reporting…

Donc dans ma nouvelle table je voudrais qqch dans ce genre là :

dossiers / nombre de véhicules / Date

Et quand on fait une update, et bien on compte le nombre de véhicules par dossier, pour chaque dossier et on ajoute les données… naturellement ya un moment où certains dossiers évoluent et donc faut les mettre à jour, et pas seulement rajouter à nouveau le dossier déjà existant…

Et ca, ben je sais pas faire :frowning: si vous avez des idées, merci de m’aider (une nouvelle fois) :smiley:

Tu as songé aux vues? Genre :

http://dev.mysql.com/doc/mysql/en/create-view.html

Ah… mySQL 5.0 :x

Passe à pgSQL 8? :smiley:

J’ai (rapidement) modélisé ma modeste base sous access histoire que ca soit plus clair.

http://img150.imageshack.us/img150/2597/database7av.th.png

View ca marche que sous des versions très récentes si je comprends bien ? Il n’y a pas moyen de gérer ca autrement ?

si c’est une table temporaire, CREATE TEMPORARY TABLE ? :neutre:

C’est pas une table temporaire, je veux garder des données “consolidées” dans une table à part. Je sais pas trop si c’est intéressant en terme de performance remarque. Je crois avoir compris que IPB avait un principe proche, c’est à dire que la table d’un sujet stocke le nombre de messages, mais que de temps en temps on fait une update en comptant effectivement le nombre de messages qui ont le topicID correspondant.

C’est une sorte de cache si l’on peut dire.

J’ai commencé à travailler mon SELECT ^^ Ca semble fonctionner correctement : mes dossiers sont bien sélectionnés, avec directement le nombre de véhicules, faut maitentant rajouter les infos client et transporteur (avec les id, pour faire des liens vers la fiche de ces gens là)

SQL
[color=blue;font-weight:bold]SELECT[/color] dossiers.codeDossier, dossiers.idDossier, COUNT(vehicules.idVehicule) AS nombreVehicules, dossiers.Date FROM dossiers, vehicules WHERE dossiers.idDossier = vehicules.idDossier GROUP BY codeDossier ORDER BY Date DESC

Après la partie compliquée sera d’insérer ca dans la base de données, et si ca existe déjà, ben faire une mise à jour ^^

Le tout sans tuer le serveur, encore que ca soit secondaire dans un premier temps :smiley:

Voui car en fait le but de tout ce merdier, c’est de faire des graphiques :smiley: J’avais oublié de le préciser :smiley: :ane:

Startide> les vues, c’est juste une requête qui crée une pseudo table :slight_smile: tu peux simuler ça en php si tu veux.

Vouais probablement… mais bon tu me connais depuis le temps ^^ j’ai progressé mais quand je demande c’est que je trouve vraiment pas comment faire, si t’as du code en rade… :smiley: :ane:

EDIT : un élément de réponse :

"Si vous spécifiez la clause ON DUPLICATE KEY UPDATE (nouveau en MySQL 4.1.0), et qu’une ligne insérée engendre un doublon pour une clé PRIMARY ou UNIQUE, une commande UPDATE sera faite à la place de l’insertion. Par exemple, les commandes ont le même effet "

Donc je mets codeDossier en clef unique, et idReport en id en primaire (auto_increment quoi, le truc classique) et là ca fera les mises à jour quand nécessaire, ca me semble pas mal non ?

Consulte bien la doc. Ca, ça doit fonctionner que sur le tables InnoDB.

Arf mairde alors :confused:

http://dev.mysql.com/doc/mysql/fr/insert.html

C’est là dedans que j’ai trouvé ca. ca semble indiquer mysql 4.x mais bon j’avoue ne pas avoir TOUT lu en détails… c moins bien fichu que le manuel de php je trouve, ca manque d’exemples bien clairs je trouve :confused: Enfin du moins j’ai du mal à les comprendre perso ^^

Bon ca progresse, doucement :slight_smile:

Ma requête fonctionne, pour peu qu’il y ait des véhicules de définis pour le dossier (de toute manière un dossier vide c’est qu’il est pas traité donc c’est pas ultra grave).

Mais le ON DUPLICATE j’arrive pas trop à comprendre comment ca fonctionne, comment l’implémenter dans ma requêtes ?

SQL
[color=blue;font-weight:bold]INSERT[/color] INTO reporting (codeDossier, idDossier, nomClient, idClient, Pays, nombreVehicules, nomTransporteur, idTransporteur, Date) [color=blue;font-weight:bold]SELECT[/color] dossiers.codeDossier, dossiers.idDossier, clients.Nom AS nomClient, clients.idClient, clients.Pays, COUNT( vehicules.idVehicule ) AS nombreVehicules, transporteurs.Nom AS nomTransporteur, transporteurs.idTransporteur, dossiers.Date FROM clients, dossiers, transporteurs, vehicules WHERE dossiers.idDossier = vehicules.idDossier AND dossiers.idClient = clients.idClient AND dossiers.idTransporteur = transporteurs.idTransporteur GROUP BY codeDossier

J’ai trouvé un “workaround” : REPLACE :slight_smile: tout simplement ^^

J’ai l’impression que ca fonctionne, en revanche en terme de perfs je crois que c’est moins bien à ce que j’ai cru comprendre.

l’inconvenient c’est que tu dois spécifier tout les champs, meme ceux que tu souhaites pas mettre à jour, sinon ils reprennent leur valeur par defaut.
le replace est valable par exemple quand t’as un formulaire identique en insertion/edition.

Ben vouais mais bon, faute de trouver la bonne syntaxe avec les autres formulations, celle ci fonctionne.

J’ai aussi remarqué que ca changeait les clefs primaire automatiques, donc ca doit faire un delete insert :slight_smile:

Comme indiqué précédement, le but était de faire du reporting :

http://img306.imageshack.us/img306/9419/graphing28yj.th.png

J’ai donc, avec ma nouvelle table, stocké mes dossiers avec le nom des clients et tout ca, et aussi le total de véhicules concerné (infos non présentes directement dans la table dossier d’origine.

Donc mon petit graphique n’est pas mal, il affiche bien le nombre de véhicules en fonction de la date du dossier.

Mais cela n’est pas suffisant, ce que je veux faire c’est afficher une année complète et le nombre de véhicules pour chaque mois… dans ma table la date du dossier est stockée sous la forme AAAA-MM-JJ

Et là j’avoue que je sais pas trop comment bricoler ca.

<?php

/* Cache de l'image */

$path = "graphing.png";
$cachefor = 1;

if (!file_exists($path) || filemtime($path) + $cachefor < time())
{

/* faire un tableau en GD */

$width = 640;
$height = 400;
$image = imagecreate($width, $height);

// couleurs utilisées
$background = imagecolorallocate($image, 218, 231, 237);
$white = imagecolorallocate($image, 255, 255, 255);
$navy = imagecolorallocate($image, 251, 192, 0);
$gray = imagecolorallocate($image, 0xc0, 0xc0, 0xc0);
$black = imagecolorallocate($image, 0, 0, 0);


// On dessine qqch ici

// Exemple 1 du président :

$Database = "bddclients";
$Username = "root";
$Password = "";
$Hostname = "localhost";

$db = mysql_connect($Hostname, $Username, $Password);
mysql_select_db($Database,$db);

$query = "SELECT nombreVehicules, Date FROM reporting";
$requeteID = mysql_query($query);
if (mysql_num_rows($requeteID))
{
	while ($array=mysql_fetch_array($requeteID))
	{
  $data[$array['Date']] = $array['nombreVehicules'];
	}
}

$maxval = max($data);
$nval = sizeof($data);

$vmargin = 20; // marge verticale (haut et bas)
$hmargin = 38; // marge horizontale (gauche et droite)

$base = floor(($width - $hmargin * 2) / $nval); // distance entre deux colonnes, calculée sur l'espace disponible, c'est à dire la largeur de l'image - la marge, le tout à diviser par le nombre de barres à tracer

$ysize = $height - 2 * $vmargin;
$xsize = $nval * $base;

imagerectangle($image, $hmargin, $vmargin, $hmargin + $xsize, $vmargin + $ysize, $black);

// Titre du graphique

$titlefont = 3;
$title = "DOI Avaries, test de graphique de reporting";

$txtsz = imagefontwidth($titlefont) * strlen($title);
$xpos = (int)($hmargin + ($xsize - $txtsz) / 2);
$xpos = max(1, $xpos);
$ypos = 3;

imagestring($image, $titlefont, $xpos, $ypos, $title, $black);

// Grille et échelles

$labelfont = 2;
$ngrid = 5;

$dydat = $maxval / $ngrid;
$dypix = $ysize / ($ngrid + 1);

for ($i = 0; $i <= ($ngrid +1); $i++)
{
	$ydat = (int)($i * $dydat);
	$ypos = $vmargin + $ysize - (int)($i*$dypix);
	
	$txtsz = imagefontwidth($labelfont) * strlen($ydat);
	$txtht = imagefontheight($labelfont);
	
	$xpos = (int)(($hmargin - $txtsz) / 2);
	$xpos = max(1, $xpos);
	
	imagestring($image, $labelfont, $xpos, $ypos - (int)($txtht/2), $ydat, $black);
	
	if (!($i == 0) && !($i > $ngrid))
  imageline($image, $hmargin - 3, $ypos, $hmargin + $xsize, $ypos, $gray);
}

// Dessiner les barres

$padding = 3;
$yscale = $ysize / (($ngrid+1) * $dydat);

for ($i = 0; list($xval, $yval) = each($data); $i++)
{
	$ymax = $vmargin + $ysize-1;
	$ymin = $ymax - (int)($yval*$yscale);
	$xmax = $hmargin + ($i+1)*$base - $padding;
	$xmin = $hmargin + $i*$base + $padding;
	
	imagefilledrectangle($image,$xmin,$ymin,$xmax,$ymax,$navy);
	
	$txtsz = imagefontwidth($labelfont) * strlen($xval);
	
	$xpos = $xmin + (int)(($base - $txtsz) / 2);
	$xpos = max($xmin, $xpos);
	$ypos = $ymax + 3;
	
	imagestring($image, $labelfont, $xpos, $ypos, $xval, $black);
	
}

// Purger l'image !!
header("Content-type: image/png"); // header : fichier image PNG
imagepng($image, $path);
imagedestroy($image);

}
header("Content-type: image/png");
readfile($path);
?>

PS : par ailleurs vous noterez un léger bug graphique sur mon graph, alors que la première date possède UN véhicule, et bien la barre arrive presque à 2 :confused: je sais pas trop à quoi cela est dû :frowning: