par
sadeq » 14 mars 2011, 18:34
Bonjour,
Permettez-moi de mettre ma plume dans ce sujet en proposant une solution.
Partant de la requête SQL de départ postée au début du sujet, je préconise de regrouper le résultat attendu par produit et par mois. Comme ça on aura pour chaque produit les quantités mensuelles. La somme des quantités mensuelles peut être obtenu par PHP dans le traitement de l'affichage.
//Requête SQL: regroupement par produit et par mois
$sql = "SELECT commandes_detail.id_produit, MONTH( date_commande ) AS mois,
CONCAT(produits.nom, ' ', produits.poids, ' ', produits.parfum) AS article,
SUM(quantite - cadeau) AS quantite_mois,
SUM(cadeau) AS cadeau_mois
FROM commandes_detail
LEFT JOIN commandes ON commandes_detail.id_commande = commandes.id
LEFT JOIN produits ON commandes_detail.id_produit = produits.id
WHERE statut = 100
GROUP BY id_produit, MONTH(date_commande)
ORDER BY id_produit, MONTH(date_commande)";
On peut consolider le résultat de cette requête SQL par PHP pour obtenir l'organisation adéquate exigée par l'affichage.
Voici donc la structure de cette organisation:
produit || quantité || janvier || février || mars ect ....
produit x || 6 || 4 || 2 || 0 et que des 0 pour les autres mois
On a besoin pour ça d'un tableau qui regroupe les données en amont par produit et en aval par mois comme ça:
$données["produit x"] : Le Niveau 1 du tableau est bien sûr le niveau produit
$données["produit x"]["quantité_totale"] : Le Niveau 2 du tableau comprend la quantité totale (somme des quantités des mois)
$données["produit x"]["mois"] : Le Niveau 2 comprend aussi un nœud nommé "mois" pour les quantités mensuelles de (janvier, février, ... etc.)
$données["produit x"]["mois"]["janvier"] : et donc les quantités sont stockées au niveau 3 (niveau de chaque mois)
$données["produit x"]["mois"]["février"]
$données["produit x"]["mois"][... etc .]
La même structure se répètera pour les autres produits à partir du Niveau 1:
$données["produit y"]
$données["produit y"]["quantité_totale"]
$données["produit y"]["mois"]["janvier"]
$données["produit y"]["mois"]["février"]
$données["produit y"]["mois"][... etc .]
Donc, un produit n'apparaitra dans ce tableau qu'une seule fois comme un nœud contenant les infos produit et surtout un sous-tableau des quantités mensuelles.
Maintenant comment obtenir cette structure hiérarchique à partir du résultat de la requête SQL? la réponse est le programme suivant:
<?php
//Se connecter à la base de données
mysql_connect("localhost","root");
mysql_select_db("test");
//Requête SQL: regroupement par produit et par mois
$sql = "SELECT commandes_detail.id_produit, MONTH( date_commande ) AS mois,
CONCAT(produits.nom, ' ', produits.poids, ' ', produits.parfum) AS article,
SUM(quantite - cadeau) AS quantite_mois,
SUM(cadeau) AS cadeau_mois
FROM commandes_detail
LEFT JOIN commandes ON commandes_detail.id_commande = commandes.id
LEFT JOIN produits ON commandes_detail.id_produit = produits.id
WHERE statut = 100
GROUP BY id_produit, MONTH(date_commande)
ORDER BY id_produit, MONTH(date_commande)";
//Exécution de la requête SQL
$resultat = mysql_query($sql);
//Tableau du résultat
$données = array();
//Création de la structure d'affichage dans le tableau $données
while ($resultat && $row = mysql_fetch_array($resultat))
{
//extraire les données utiles aux index de niveaux du tableau : produit et mois
$produit = $row["id_produit"];
$mois = $row["mois"];
//créer les noeuds produit du tableau s'ils n'existent pas, sinon ils seront mis à jour pour consolider les données par produit
if (!isset($données[$produit]))
{
$données[$produit] = array();
$données[$produit]["mois"] = array();
$données[$produit]["quantité_totale"] = 0;
}
//mettre à jour les données (quantités et quantité totale) du tableau $données
$données[$produit]["mois"][$mois] = $row["quantite_mois"]; //niveau 3 du tableau : quantités mensuelles du produit
//Cumuler les quantités du produit pour obtenir un total
$données[$produit]["quantité_totale"] += $row["quantite_mois"]; //somme des quantités mensuelles du produit
}
//Affichage du tableau résultat
echo "<table border='1'><tr><th>Produit</th><th>Qté Totale</th><th>Janvier</th><th>Février</th><th>Mars</th><th> ... les autres mois ...</th></tr>";
foreach($données as $produit=>$ligne) //niveau 1 du tableau
{
//1 produit par ligne composée par 1 colonne par mois
// on commence par le produit et la quantité totale dans les 2 premières colonnes
echo "<tr><td>" . $produit . "</td><td>". $ligne["quantité_totale"] . "</td>"; // niveau 2 du tableau : produit et qté totale
// en suite les quantités mensuelles dans les colonnes suivantes
foreach($ligne["mois"] as $mois=>$quantité_mois)
{
echo "<td>". $quantité_mois . "</td>"; //niveau 3 du tableau : qté mensuelles
}
//fin de la ligne produit
echo "</tr>";
}
//fin de l'affichage
echo "</table>";
?>
Voici ma base de données de test:
-- phpMyAdmin SQL Dump
-- version 3.3.9
-- http://www.phpmyadmin.net
--
-- Serveur: localhost
-- Généré le : Lun 14 Mars 2011 à 18:50
-- Version du serveur: 5.5.8
-- Version de PHP: 5.3.5
SET SQL_MODE="NO_AUTO_VALUE_ON_ZERO";
/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */;
/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */;
/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */;
/*!40101 SET NAMES utf8 */;
--
-- Base de données: `test`
--
-- --------------------------------------------------------
--
-- Structure de la table `commandes`
--
CREATE TABLE IF NOT EXISTS `commandes` (
`id` int(11) DEFAULT NULL,
`date_commande` datetime DEFAULT NULL,
`statut` int(11) DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
--
-- Contenu de la table `commandes`
--
INSERT INTO `commandes` (`id`, `date_commande`, `statut`) VALUES
(1, '2011-01-01 00:00:00', 100),
(2, '2011-02-01 00:00:00', 100),
(3, '2011-03-01 00:00:00', 100);
-- --------------------------------------------------------
--
-- Structure de la table `commandes_detail`
--
CREATE TABLE IF NOT EXISTS `commandes_detail` (
`id_commande` int(11) DEFAULT NULL,
`id_produit` int(11) DEFAULT NULL,
`quantite` int(11) DEFAULT NULL,
`cadeau` int(11) DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
--
-- Contenu de la table `commandes_detail`
--
INSERT INTO `commandes_detail` (`id_commande`, `id_produit`, `quantite`, `cadeau`) VALUES
(1, 1, 5, 0),
(1, 2, 10, 0),
(2, 2, 20, 0),
(3, 1, 15, 1),
(3, 2, 15, 1);
-- --------------------------------------------------------
--
-- Structure de la table `produits`
--
CREATE TABLE IF NOT EXISTS `produits` (
`id` int(11) DEFAULT NULL,
`nom` varchar(50) DEFAULT NULL,
`poids` int(11) DEFAULT NULL,
`parfum` varchar(50) DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
--
-- Contenu de la table `produits`
--
INSERT INTO `produits` (`id`, `nom`, `poids`, `parfum`) VALUES
(1, 'Produit 1', 1, '1'),
(2, 'Produit 2', 1, '1');
*
Et voici le résultat d'exécution de mon programme:
Produit___Qté Totale ___Janvier___Février___Mars___... les autres mois ...
1__________19 __________5________14
2__________44 __________10_______20 ____14
Voilà.
Bonjour,
Permettez-moi de mettre ma plume dans ce sujet en proposant une solution.
Partant de la requête SQL de départ postée au début du sujet, je préconise de regrouper le résultat attendu par produit et par mois. Comme ça on aura pour chaque produit les quantités mensuelles. La somme des quantités mensuelles peut être obtenu par PHP dans le traitement de l'affichage.
[php]
//Requête SQL: regroupement par produit et par mois
$sql = "SELECT commandes_detail.id_produit, MONTH( date_commande ) AS mois,
CONCAT(produits.nom, ' ', produits.poids, ' ', produits.parfum) AS article,
SUM(quantite - cadeau) AS quantite_mois,
SUM(cadeau) AS cadeau_mois
FROM commandes_detail
LEFT JOIN commandes ON commandes_detail.id_commande = commandes.id
LEFT JOIN produits ON commandes_detail.id_produit = produits.id
WHERE statut = 100
GROUP BY id_produit, MONTH(date_commande)
ORDER BY id_produit, MONTH(date_commande)";
[/php]
On peut consolider le résultat de cette requête SQL par PHP pour obtenir l'organisation adéquate exigée par l'affichage.
Voici donc la structure de cette organisation:
[quote]produit || quantité || janvier || février || mars ect ....
produit x || 6 || 4 || 2 || 0 et que des 0 pour les autres mois[/quote]
On a besoin pour ça d'un tableau qui regroupe les données en amont par produit et en aval par mois comme ça:
$données["produit x"] : Le Niveau 1 du tableau est bien sûr le niveau produit
$données["produit x"]["quantité_totale"] : Le Niveau 2 du tableau comprend la quantité totale (somme des quantités des mois)
$données["produit x"]["mois"] : Le Niveau 2 comprend aussi un nœud nommé "mois" pour les quantités mensuelles de (janvier, février, ... etc.)
$données["produit x"]["mois"]["janvier"] : et donc les quantités sont stockées au niveau 3 (niveau de chaque mois)
$données["produit x"]["mois"]["février"]
$données["produit x"]["mois"][... etc .]
La même structure se répètera pour les autres produits à partir du Niveau 1:
$données["produit y"]
$données["produit y"]["quantité_totale"]
$données["produit y"]["mois"]["janvier"]
$données["produit y"]["mois"]["février"]
$données["produit y"]["mois"][... etc .]
Donc, un produit n'apparaitra dans ce tableau qu'une seule fois comme un nœud contenant les infos produit et surtout un sous-tableau des quantités mensuelles.
Maintenant comment obtenir cette structure hiérarchique à partir du résultat de la requête SQL? la réponse est le programme suivant:
[php]
<?php
//Se connecter à la base de données
mysql_connect("localhost","root");
mysql_select_db("test");
//Requête SQL: regroupement par produit et par mois
$sql = "SELECT commandes_detail.id_produit, MONTH( date_commande ) AS mois,
CONCAT(produits.nom, ' ', produits.poids, ' ', produits.parfum) AS article,
SUM(quantite - cadeau) AS quantite_mois,
SUM(cadeau) AS cadeau_mois
FROM commandes_detail
LEFT JOIN commandes ON commandes_detail.id_commande = commandes.id
LEFT JOIN produits ON commandes_detail.id_produit = produits.id
WHERE statut = 100
GROUP BY id_produit, MONTH(date_commande)
ORDER BY id_produit, MONTH(date_commande)";
//Exécution de la requête SQL
$resultat = mysql_query($sql);
//Tableau du résultat
$données = array();
//Création de la structure d'affichage dans le tableau $données
while ($resultat && $row = mysql_fetch_array($resultat))
{
//extraire les données utiles aux index de niveaux du tableau : produit et mois
$produit = $row["id_produit"];
$mois = $row["mois"];
//créer les noeuds produit du tableau s'ils n'existent pas, sinon ils seront mis à jour pour consolider les données par produit
if (!isset($données[$produit]))
{
$données[$produit] = array();
$données[$produit]["mois"] = array();
$données[$produit]["quantité_totale"] = 0;
}
//mettre à jour les données (quantités et quantité totale) du tableau $données
$données[$produit]["mois"][$mois] = $row["quantite_mois"]; //niveau 3 du tableau : quantités mensuelles du produit
//Cumuler les quantités du produit pour obtenir un total
$données[$produit]["quantité_totale"] += $row["quantite_mois"]; //somme des quantités mensuelles du produit
}
//Affichage du tableau résultat
echo "<table border='1'><tr><th>Produit</th><th>Qté Totale</th><th>Janvier</th><th>Février</th><th>Mars</th><th> ... les autres mois ...</th></tr>";
foreach($données as $produit=>$ligne) //niveau 1 du tableau
{
//1 produit par ligne composée par 1 colonne par mois
// on commence par le produit et la quantité totale dans les 2 premières colonnes
echo "<tr><td>" . $produit . "</td><td>". $ligne["quantité_totale"] . "</td>"; // niveau 2 du tableau : produit et qté totale
// en suite les quantités mensuelles dans les colonnes suivantes
foreach($ligne["mois"] as $mois=>$quantité_mois)
{
echo "<td>". $quantité_mois . "</td>"; //niveau 3 du tableau : qté mensuelles
}
//fin de la ligne produit
echo "</tr>";
}
//fin de l'affichage
echo "</table>";
?>
[/php]
Voici ma base de données de test:
[sql]
-- phpMyAdmin SQL Dump
-- version 3.3.9
-- http://www.phpmyadmin.net
--
-- Serveur: localhost
-- Généré le : Lun 14 Mars 2011 à 18:50
-- Version du serveur: 5.5.8
-- Version de PHP: 5.3.5
SET SQL_MODE="NO_AUTO_VALUE_ON_ZERO";
/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */;
/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */;
/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */;
/*!40101 SET NAMES utf8 */;
--
-- Base de données: `test`
--
-- --------------------------------------------------------
--
-- Structure de la table `commandes`
--
CREATE TABLE IF NOT EXISTS `commandes` (
`id` int(11) DEFAULT NULL,
`date_commande` datetime DEFAULT NULL,
`statut` int(11) DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
--
-- Contenu de la table `commandes`
--
INSERT INTO `commandes` (`id`, `date_commande`, `statut`) VALUES
(1, '2011-01-01 00:00:00', 100),
(2, '2011-02-01 00:00:00', 100),
(3, '2011-03-01 00:00:00', 100);
-- --------------------------------------------------------
--
-- Structure de la table `commandes_detail`
--
CREATE TABLE IF NOT EXISTS `commandes_detail` (
`id_commande` int(11) DEFAULT NULL,
`id_produit` int(11) DEFAULT NULL,
`quantite` int(11) DEFAULT NULL,
`cadeau` int(11) DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
--
-- Contenu de la table `commandes_detail`
--
INSERT INTO `commandes_detail` (`id_commande`, `id_produit`, `quantite`, `cadeau`) VALUES
(1, 1, 5, 0),
(1, 2, 10, 0),
(2, 2, 20, 0),
(3, 1, 15, 1),
(3, 2, 15, 1);
-- --------------------------------------------------------
--
-- Structure de la table `produits`
--
CREATE TABLE IF NOT EXISTS `produits` (
`id` int(11) DEFAULT NULL,
`nom` varchar(50) DEFAULT NULL,
`poids` int(11) DEFAULT NULL,
`parfum` varchar(50) DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
--
-- Contenu de la table `produits`
--
INSERT INTO `produits` (`id`, `nom`, `poids`, `parfum`) VALUES
(1, 'Produit 1', 1, '1'),
(2, 'Produit 2', 1, '1');
[/sql]*
Et voici le résultat d'exécution de mon programme:
[quote]
Produit___Qté Totale ___Janvier___Février___Mars___... les autres mois ...
1__________19 __________5________14
2__________44 __________10_______20 ____14
[/quote]
Voilà.