Page 1 sur 1

Recherche les 2 derniers enregistrements selon critères !

Posté : 02 sept. 2009, 18:02
par fawi
Bonjour,
Je débute en php et je suis un peu peru avec les bases de données.

J'ai deux tables (la première "CLIENT" détermine le client, la seconde "TRANSACTIONS" les transactions effectuées)
Je souhaiterais selectionner les deux dernière transaction d'un client, pour ensuite effectuer un calcul sur ces deux dernière transactions.
Ex. : Client MARCEL (id27)
recherche les 2 dernières transactions du client MARCEL
- 27/02/2007, 121€.
- 17/06/2009, 210€
Pour ensuite effectuer un calcul : savoir si il y a augmentation ou diminution du montant de la commande
Dans cet exemple : Augmentation !

Je sais comment effectuer la recherche des transaction du client mais pas comment faire pour n'avoir que les 2 dernières transactions !
Merci d'avance pour votre aide

Re: Recherche les 2 derniers enregistrements selon critères !

Posté : 02 sept. 2009, 18:14
par stopher
Salut ,

si tu as un index par exemple "id" , quie est auto incrémenté , tu peux dans ce cas , faire une requete de ce type :
SELECT < tes champs > WHERE < tes conditions > ORDER BY id DESC LIMIT 2
Ca me parait le plus simple :-)

Ch.

Re: Recherche les 2 derniers enregistrements selon critères !

Posté : 02 sept. 2009, 21:48
par fawi
Bien vu !!!
C'est une excellente idée, j'essae ca demain.

Re: Recherche les 2 derniers enregistrements selon critères !

Posté : 03 sept. 2009, 00:40
par ouckileou
Ca me parait le plus simple :-)
Non le plus simple, et surtout le plus logique, c'est de faire la même requête mais en utilisant la date...

Quoi de mieux que la date d'enregistrement pour retrouver les deux dernières commandes ? D'autant que tu n'es jamais à l'abri que le sgbd ait "comblé les trous", et que la commande numéro 6 ait été passée après la 24 :)

Re: Recherche les 2 derniers enregistrements selon critères !

Posté : 03 sept. 2009, 05:01
par AB
Ca me parait le plus simple :-)
Non le plus simple, et surtout le plus logique, c'est de faire la même requête mais en utilisant la date...

Quoi de mieux que la date d'enregistrement pour retrouver les deux dernières commandes ? D'autant que tu n'es jamais à l'abri que le sgbd ait "comblé les trous", et que la commande numéro 6 ait été passée après la 24 :)
Ben c'est pas évident. Dans l'absolu il peut y avoir plusieurs commandes possédant la même date. Auquel cas il serait mieux d'utiliser un datetime et encore. Mais pour l'exemple de fawi et puisqu'il s'agit non pas des deux dernières commandes, mais des deux dernières commandes du même client, faire une requête sur le champ date est suffisant pour l'usage qu'il en fait.

Juste une précision, la réponse de stopher est la plus simple dans l'absolu pour trouver les derniers enregistrements - comparativement à un champ date ou datetime qui peuvent avoir les mêmes valeurs dans de nombreuses lignes - à condition d'utiliser les tables MyISAM dont les valeurs AUTO_INCREMENT ne sont jamais réutilisées.
Mais effectivement cette solution est moins portable.

Re: Recherche les 2 derniers enregistrements selon critères !

Posté : 03 sept. 2009, 07:03
par sadeq
Le plus juste est de se baser sur la date de la commande et non sur des numéros dont la raison d'être est plutôt technique que métier.

Donc, la requête qui trouve les 2 dernières commande du client n°27 est la suivante:
SELECT id, date, montant FROM commandes WHERE id = 27 ORDER BY date DESC LIMIT 2
Et celle qui calcule l'écart entre les montants de ces commandes est :
DELIMITER |
CREATE PROCEDURE `ecart_commandes`(id_client INT)
BEGIN
  DECLARE date1, date2 DATETIME;  
  DECLARE montant1, montant2, ecart FLOAT;
  DECLARE comment VARCHAR(20);
  DECLARE curseur1 CURSOR FOR SELECT  c.date, c.montant FROM commandes c WHERE c.id = id_client ORDER BY c.date DESC LIMIT 2;
  CREATE TABLE IF NOT EXISTS ecart_com (id_client int, date1 datetime, montant1 float, date2 datetime, montant2 float, ecart float, comment varchar(255));

  OPEN curseur1;
  FETCH curseur1 INTO date1, montant1;
  FETCH curseur1 INTO date2, montant2; 
  SET ecart = montant1 - montant2;

  IF montant1 = montant2 THEN
      SET comment = 'Egalité';
  ELSE
      IF montant1 < montant2 THEN
         SET comment = 'Diminution';
      ELSE
         SET comment = 'Augmentation';
      END IF;
  END IF;

  INSERT INTO ecart_com (id_client, date1, montant1, date2, montant2, ecart, comment) VALUES (id_client, date1, montant1, date2, montant2, ecart, comment);
  CLOSE curseur1;
END
Cette procédure stockée permet donc de lire le curseur de la requête qui sélectionne les 2 dernières commandes d'un client donné et de calculer l'écart entre les montants de ses commandes (en plus d'un commentaire sur l'écart)
Le résultat de calcul est inséré dans une table de résultat qu'on a nommée "ecart_com".

Pour exécuter cette procédure stockée pour le client n°27, il faut exécuter la requête suivante:
call ecart_commandes(27);
Voici la base de données de test que j'ai créée et testé:
-- phpMyAdmin SQL Dump
-- version 3.2.0.1
-- http://www.phpmyadmin.net
--
-- Serveur: localhost
-- Généré le : Jeu 03 Septembre 2009 à 05:40
-- Version du serveur: 5.1.31
-- Version de PHP: 5.3.0

SET SQL_MODE="NO_AUTO_VALUE_ON_ZERO";

--
-- Base de données: `test`
--

-- --------------------------------------------------------

--
-- Structure de la table `commandes`
--

CREATE TABLE IF NOT EXISTS `commandes` (
  `id` int(11) NOT NULL,
  `date` datetime NOT NULL,
  `montant` float NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=latin1;

--
-- Contenu de la table `commandes`
--

INSERT INTO `commandes` (`id`, `date`, `montant`) VALUES
(27, '2009-08-10 07:17:21', 500),
(27, '2009-08-17 07:17:46', 400),
(27, '2009-09-01 07:18:16', 200);

-- --------------------------------------------------------

--
-- Structure de la table `ecart_com`
--

CREATE TABLE IF NOT EXISTS `ecart_com` (
  `id_client` int(11) DEFAULT NULL,
  `date1` datetime DEFAULT NULL,
  `montant1` float DEFAULT NULL,
  `date2` datetime DEFAULT NULL,
  `montant2` float DEFAULT NULL,
  `ecart` float DEFAULT NULL,
  `comment` varchar(255) DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=latin1;


DELIMITER $$
--
-- Procédures
--
CREATE DEFINER=`root`@`localhost` PROCEDURE `ecart_commandes`(id_client INT)
BEGIN
  DECLARE date1, date2 DATETIME;  
  DECLARE montant1, montant2, ecart FLOAT;
  DECLARE comment VARCHAR(20);
  DECLARE curseur1 CURSOR FOR SELECT  c.date, c.montant FROM commandes c WHERE c.id = id_client ORDER BY c.date DESC LIMIT 2;
  CREATE TABLE IF NOT EXISTS ecart_com (id_client int, date1 datetime, montant1 float, date2 datetime, montant2 float, ecart float, comment varchar(255));

  OPEN curseur1;
  FETCH curseur1 INTO date1, montant1;
  FETCH curseur1 INTO date2, montant2; 
  SET ecart = montant1 - montant2;

  IF montant1 = montant2 THEN
      SET comment = 'Egalité';
  ELSE
      IF montant1 < montant2 THEN
         SET comment = 'Diminution';
      ELSE
         SET comment = 'Augmentation';
      END IF;
  END IF;

  INSERT INTO ecart_com (id_client, date1, montant1, date2, montant2, ecart, comment) VALUES (id_client, date1, montant1, date2, montant2, ecart, comment);
  CLOSE curseur1;
END$$

DELIMITER ;
D'après cet exemple, le résultat qu'on obtient dans la table des résultats qu'on a nommée "ecart_com" et qui est remplie par la procédure "ecart_commandes" pour le client n°27 est le suivant:

Code : Tout sélectionner

id_client date1 montant1 date2 montant2 ecart comment 27 2009-09-01 200 2009-08-17 400 200 Diminution

Re: Recherche les 2 derniers enregistrements selon critères !

Posté : 03 sept. 2009, 08:08
par stopher
Merci pour ces précisions , je ne saivais pas que certains SGBD pouvaient réutiliser des id qui n'existent plus ...

Et quand je vois la procédure de Sadeq , cela me conforte dans mon idée , "Faut vraiment que je me penche plus sur le SQL" :D

Pour revenir au problème de fawi si l'on se base sur les date format ( Y-m-d ), imaginons , qu'il y a trois enregistrements au même jour , les deux enregistrements qui ressortent sur les trois seront aléatoires ?

Re: Recherche les 2 derniers enregistrements selon critères !

Posté : 03 sept. 2009, 09:56
par fawi
Merci a tous pour autant de précision e de rapidité.

Je ne m'attendais pas a ce que soit aussi technique mais le résultat est parfait !

Re: Recherche les 2 derniers enregistrements selon critères !

Posté : 03 sept. 2009, 12:07
par ouckileou
Ca me parait le plus simple :-)
Non le plus simple, et surtout le plus logique, c'est de faire la même requête mais en utilisant la date...

Quoi de mieux que la date d'enregistrement pour retrouver les deux dernières commandes ? D'autant que tu n'es jamais à l'abri que le sgbd ait "comblé les trous", et que la commande numéro 6 ait été passée après la 24 :)
Ben c'est pas évident. Dans l'absolu il peut y avoir plusieurs commandes possédant la même date. Auquel cas il serait mieux d'utiliser un datetime et encore. Mais pour l'exemple de fawi et puisqu'il s'agit non pas des deux dernières commandes, mais des deux dernières commandes du même client, faire une requête sur le champ date est suffisant pour l'usage qu'il en fait.

Juste une précision, la réponse de stopher est la plus simple dans l'absolu pour trouver les derniers enregistrements - comparativement à un champ date ou datetime qui peuvent avoir les mêmes valeurs dans de nombreuses lignes - à condition d'utiliser les tables MyISAM dont les valeurs AUTO_INCREMENT ne sont jamais réutilisées.
Mais effectivement cette solution est moins portable.
Mouais, je trouve que tu chipotes et que ton message n'est pas très convaincant. Bien sur qu'on se base sur la demande du posteur, donc obtenir les dernières commandes du client ben c'est avec la date. Parce que pour trier par ordre chronologique y'a pas mieux qu'une date (oui date/heure tu fais bien de préciser, et je ne comprends pas le "et encore" au sujet du datetime). On devrait pas avoir besoin de manipuler les clés, ce n'est pas parce que c'est plus simple "dans l'absolu" que c'est mieux :) (bien que je ne vois pas bien la difficulté supplémentaire de trier sur des dates)

À part ça si le sujet est résolu, merci de cliqueter sur le bouton vert de la réponse qui convient.

Re: Recherche les 2 derniers enregistrements selon critères !

Posté : 03 sept. 2009, 21:12
par AB
Mouais, je trouve que tu chipotes et que ton message n'est pas très convaincant. Bien sur qu'on se base sur la demande du posteur, donc obtenir les dernières commandes du client ben c'est avec la date. Parce que pour trier par ordre chronologique y'a pas mieux qu'une date (oui date/heure tu fais bien de préciser, et je ne comprends pas le "et encore" au sujet du datetime). On devrait pas avoir besoin de manipuler les clés, ce n'est pas parce que c'est plus simple "dans l'absolu" que c'est mieux :) (bien que je ne vois pas bien la difficulté supplémentaire de trier sur des dates)
Ben c'est juste que je me posais la même question que stopher quelques messages plus haut. Dans l'absolu (sans reprendre précisément la demande du posteur) si je veux connaître les deux dernières commandes d'un site, il peut y avoir plus d'une dizaine de commandes durant la même seconde et c'est pour cette raison que je disais "et encore" au sujet du datetime :-k

Sinon je voulais juste préciser que certaines tables (dont MyIsam) ont des valeurs auto incrément qui ne sont jamais réutilisées, mais que ce n'est pas un cas général :)