Probleme avec sous requete MYSQL

Eléphant du PHP | 89 Messages

24 févr. 2010, 19:26

Bonjour à tous!
Je posséde dans une base MYSQL une table d'articles achetés avec les dates d'achats et les coordonnées mail des acheteurs, voici la structure de la table
id_article | article | date_achat | mail_achat
J'aurais souhaité savoir quels sont les articles achetés par les mêmes acheteurs...mais pour plusieurs périodes définies
Ex : Quels sont les mêmes personnes ayant acheté entre le 1er février et le 3 février...entre le 6 mars et le 13 mars ...Entre le 5 mai et le 1er juin.
Pour ce qui est de deux périodes j'ai trouvé la requête suivante ..et ça marche j'obtiens les acheteurs ayant acheté au moins deux fois pour les périodes données :
SELECT mail_achat , article FROM table WHERE date_achat  [i]***1ere PERIODE*** [/i]BETWEEN '2009-02-01' AND  '2009-02-03'  AND mail_achat IN (select mail_achat FROM table WHERE date_achat [i]***2eme PERIODE***  [/i]BETWEEN '2009-03-06' AND  '2009-03-13' ) GROUP BY mail_achat  HAVING mail_achat >1
Mais quand je rajoute une période je n'obtiens plus aucun résultat
 SELECT mail_achat , article FROM table WHERE date_achat [i]***1ere PERIODE*** [/i] BETWEEN '2009-02-01' AND  '2009-02-03'  AND mail_achat IN (select mail_achat FROM table WHERE date_achat [i]***2eme PERIODE*** [/i] BETWEEN '2009-03-06' AND  '2009-03-13' ) AND mail_achat IN (select mail_achat FROM table WHERE date_achat [i]***3eme PERIODE*** [/i] BETWEEN '2009-05-05' AND  '2009-06-01' ) GROUP BY mail_achat  HAVING mail_achat >1
Si quelqu'un a une idée plus simple ...et surtout efficace alors merci d'avance!!!

Modérateur PHPfrance
Modérateur PHPfrance | 6373 Messages

24 févr. 2010, 19:39

Je suis pas sûr de comprendre.

Si j'ai acheté 2 fois dans chaque période, est-ce que tu veux obtenir 6, ou 2+période/2+période/2+période ?

Merci d'utiliser les balises
, ton code n'est pas très lisible.

Eléphant du PHP | 89 Messages

24 févr. 2010, 19:51

Désolé ça n'a pas l'air de marcher même pour deux périodes...J'ai essayé cette clause mais à chaque fois il ne me retourne aucun enregistrement (sachant qu'il y en a) et si je fais OR au lieu de AND alors il me sort tous les clients de la 1ere periode et tous les clients de la deuxiéme période ou aucun si je précise >1

Modérateur PHPfrance
Modérateur PHPfrance | 6373 Messages

24 févr. 2010, 19:55

J'ai édité mon message car je ne comprends pas bien. Peux-tu nous donner un exemple de données et un exemple de ce que tu voudrais en sortie ?

Idéalement je veux bien le SQL de création de table et les INSERT pour insérer des données de tests, si tu peux.

Eléphant du PHP | 89 Messages

24 févr. 2010, 19:58

Désolé pour la balise SQL je l'ai fait expres pour mieux commenter mon code (1ere période,etc...) en italique (si je mettais SQL il me mettait le code avec des balises HTML)
Pour en revenir à la requete ...Je veux savoir quels sont les clients qui ont acheté à la fois à la 1ere période ET à la deuxiéme période ET à la troisiéme période
EX: TOTO a acheté 1 article pendant la 1ere période et 6 articles pendant la deuxiéme et 1 article pendant la 3eme,etc...il m'interesse
Si TOTO n'avait acheté que X articles pendant la 1ere période et pas les autres, il ne m'interesse pas

Modérateur PHPfrance
Modérateur PHPfrance | 6373 Messages

24 févr. 2010, 20:02

Ok c'est plus clair

Pour ce qui est du SQL de la table et des données, on peut l'avoir ? (de quoi faire des essais seulement)

Eléphant du PHP | 89 Messages

24 févr. 2010, 21:01

Désolé pour les données mais il s'agit d'un fichier client nominatif (mon patron serait peut-être un peu furax!!!)
voici la structure de la table(cette fois çi avec balises)
-- phpMyAdmin SQL Dump
-- version 3.3.0-alpha1
-- http://www.phpmyadmin.net
--
-- Serveur: localhost
-- Généré le : Mer 24 Février 2010 à 18:58
-- Version du serveur: 5.1.36
-- Version de PHP: 5.3.0

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: `client`
--

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

--
-- Structure de la table `articles`
--

CREATE TABLE IF NOT EXISTS `articles` (
  `id_article` int(11) NOT NULL,
  `article` varchar(50) NOT NULL,
  `date_achat` datetime NOT NULL,
  `mail_achat` varchar(50) NOT NULL,
  `id_acheteur` int(11) NOT NULL,
  PRIMARY KEY (`id_article`),
  KEY `mail_achat` (`mail_achat`),
  KEY `id_acheteur` (`id_acheteur`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;

--
-- Contenu de la table `articles`
--

Modérateur PHPfrance
Modérateur PHPfrance | 6373 Messages

25 févr. 2010, 13:39

Je crois que ça ça marche :
-- Tous les clients qui ont acheté au moins une fois durant les 3 périodes
SELECT a1.mail_achat, a1.date_achat as achat_period, a2.date_achat, a3.date_achat
FROM articles a1
INNER JOIN articles a2 ON a1.id_acheteur = a2.id_acheteur
INNER JOIN articles a3 ON a2.id_acheteur = a3.id_acheteur
WHERE a1.date_achat BETWEEN '2009-02-01' AND '2009-02-03'
AND a2.date_achat BETWEEN '2009-03-06' AND '2009-03-13'
AND a3.date_achat BETWEEN '2009-05-05' AND '2009-06-01';
Si une personne a fait plusieurs achats durant la même période, on aura plusieurs lignes, donc il suffit de les compter et d'enlever ceux qui n'en n'ont qu'une (si c'est ce que tu veux faire, au début c'est ce que j'ai compris) :
-- Les clients qui ont acheté au moins une fois durant les 3 périodes,
-- et plus d'une fois sur au moins une période
SELECT a1.mail_achat
FROM articles a1
INNER JOIN articles a2 ON a1.id_acheteur = a2.id_acheteur
INNER JOIN articles a3 ON a2.id_acheteur = a3.id_acheteur
WHERE a1.date_achat BETWEEN '2009-02-01' AND '2009-02-03'
AND a2.date_achat BETWEEN '2009-03-06' AND '2009-03-13'
AND a3.date_achat BETWEEN '2009-05-05' AND '2009-06-01'
GROUP BY a1.mail_achat
HAVING COUNT(*)>1;
Bon après si tu as plus de période à traiter ça devient un peu rigiden, et il faut voir avec un nombre de données important pour tester les performances, mais je pense que les jointures iront mieux que les sous-requêtes :)

Eléphant du PHP | 89 Messages

26 févr. 2010, 17:43

Désolé le INNER JOIN ne fonctionne pas.
:D :D En revanche j'ai imbriqué les sous requête en déplacant les parenthéses et là ça marche!! :D :D
SELECT mail_achat , article FROM TABLE WHERE date_achat  ***1ere PERIODE*** AND mail_achat IN (SELECT mail_achat FROM TABLE WHERE date_achat  ***2EME PERIODE*** AND  mail_achat IN (SELECT mail_achat FROM TABLE WHERE date_achat ***3EME PERIODE***)) GROUP BY mail_achat  HAVING mail_achat >1
Merci ouckileou et à la prochaine !!!
PS :J'aurais souhaité mettre le sujet comme résolu mais je ne trouve pas où cocher la case!

Modérateur PHPfrance
Modérateur PHPfrance | 6373 Messages

26 févr. 2010, 17:47

Désolé le INNER JOIN ne fonctionne pas.
:shock:

Déjà il faut arrêter de dire "ne marche pas" ou "ne fonctionne pas" : ça veut dire quoi, message d'erreur MySQL ? Résultats bizarres ou pas de résultats ?

mais ça m'étonne quand même...
PS :J'aurais souhaité mettre le sujet comme résolu mais je ne trouve pas où cocher la case!
Le petit bouton vert en haut à droite de chaque message.