IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

PHP & Base de données Discussion :

Clients n'ayant pas commandé depuis n mois


Sujet :

PHP & Base de données

  1. #1
    Nouveau membre du Club
    Profil pro
    Développeur Web
    Inscrit en
    Septembre 2003
    Messages
    30
    Détails du profil
    Informations personnelles :
    Âge : 50
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Développeur Web

    Informations forums :
    Inscription : Septembre 2003
    Messages : 30
    Points : 26
    Points
    26
    Par défaut Clients n'ayant pas commandé depuis n mois
    Bonjour,


    Langage MySQL 4 + PHP 4

    J'ai fait une requête pour renvoyer tous les clients n'ayant pas commandé depuis n mois mais je pense qu'elle n'est pas optimum.

    Structure des tables :

    La table des clients :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    CREATE TABLE `clients` (
      `cli_id` bigint(20) unsigned NOT NULL auto_increment,
      `cli_date` date default NULL,
      PRIMARY KEY  (`cli_id`)
    );
    La table d'en-tête des commandes :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    CREATE TABLE `commandes` (
      `cmd_id` bigint(20) unsigned zerofill NOT NULL auto_increment,
      `cli_id` bigint(20) unsigned NOT NULL,
      `cmd_date` datetime NOT NULL default '0000-00-00 00:00:00',
      PRIMARY KEY  (`cmd_id`)
    );
    Merci de votre aide

  2. #2
    Expert éminent
    Avatar de Swoög
    Profil pro
    Inscrit en
    Janvier 2003
    Messages
    6 045
    Détails du profil
    Informations personnelles :
    Âge : 37
    Localisation : France

    Informations forums :
    Inscription : Janvier 2003
    Messages : 6 045
    Points : 8 339
    Points
    8 339
    Par défaut
    Si tu pouvais nous donner la requête en question... ça serait plus simple... la meilleur que je vois pour le moment est :

    @mois est le nombre de moins (ton N)

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    SELECT CLI.cli_id
    FROM clients CLI
      LEFT JOIN commandes COM
        ON COM.cli_id = CLI.cli_id
    WHERE
      PERIOD_DIFF(DATE_FORMAT(CLI.cli_date, '%Y%m'), DATE_FORMAT(NOW(), '%Y%m')) > @mois
      AND (
        MAX(COM.cmd_date) IS NULL
        OR
        PERIOD_DIFF(DATE_FORMAT(MAX(COM.cmd_date), '%Y%m'), DATE_FORMAT(NOW(), '%Y%m')) > @mois
      )
    GROUP BY CLI.cli_id

  3. #3
    Nouveau membre du Club
    Profil pro
    Développeur Web
    Inscrit en
    Septembre 2003
    Messages
    30
    Détails du profil
    Informations personnelles :
    Âge : 50
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Développeur Web

    Informations forums :
    Inscription : Septembre 2003
    Messages : 30
    Points : 26
    Points
    26
    Par défaut
    Merci de ton aide, j'ai essayé ta requête mais j'ai une erreur :
    'invalid use of group function'

  4. #4
    Membre expert
    Avatar de Alexandre T
    Homme Profil pro
    Chef de projets AMO
    Inscrit en
    Mai 2002
    Messages
    1 213
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 48
    Localisation : France, Gironde (Aquitaine)

    Informations professionnelles :
    Activité : Chef de projets AMO
    Secteur : Transports

    Informations forums :
    Inscription : Mai 2002
    Messages : 1 213
    Points : 3 001
    Points
    3 001
    Par défaut
    Swoög a juste fait une petite étourderie (de copier-coller sans doute).

    La ligne GROUP BY doit être la dernière ligne normalement.

  5. #5
    Expert éminent
    Avatar de Swoög
    Profil pro
    Inscrit en
    Janvier 2003
    Messages
    6 045
    Détails du profil
    Informations personnelles :
    Âge : 37
    Localisation : France

    Informations forums :
    Inscription : Janvier 2003
    Messages : 6 045
    Points : 8 339
    Points
    8 339
    Par défaut
    Citation Envoyé par Alexandre T
    Swoög a juste fait une petite étourderie (de copier-coller sans doute).

    La ligne GROUP BY doit être la dernière ligne normalement.
    J'ai toujours un peu de mal avec l'ordre de différentes lignes... désolé, j'édite

  6. #6
    Nouveau membre du Club
    Profil pro
    Développeur Web
    Inscrit en
    Septembre 2003
    Messages
    30
    Détails du profil
    Informations personnelles :
    Âge : 50
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Développeur Web

    Informations forums :
    Inscription : Septembre 2003
    Messages : 30
    Points : 26
    Points
    26
    Par défaut
    J'ai encore la même erreur, j'avais effectivement corrigé l'ordre.

    Il semblerait qu'il n'accepte pas 2 conditions.

    Avez-vous testé ?

    Merci

  7. #7
    Nouveau membre du Club
    Profil pro
    Développeur Web
    Inscrit en
    Septembre 2003
    Messages
    30
    Détails du profil
    Informations personnelles :
    Âge : 50
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Développeur Web

    Informations forums :
    Inscription : Septembre 2003
    Messages : 30
    Points : 26
    Points
    26
    Par défaut
    N'ayant pas trouvé de solution, je relance le post :

    Citation Envoyé par Swoög
    Si tu pouvais nous donner la requête en question... ça serait plus simple... la meilleur que je vois pour le moment est :

    @mois est le nombre de moins (ton N)

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    SELECT CLI.cli_id
    FROM clients CLI
      LEFT JOIN commandes COM
        ON COM.cli_id = CLI.cli_id
    WHERE
      PERIOD_DIFF(DATE_FORMAT(CLI.cli_date, '%Y%m'), DATE_FORMAT(NOW(), '%Y%m')) > @mois
      AND (
        MAX(COM.cmd_date) IS NULL
        OR
        PERIOD_DIFF(DATE_FORMAT(MAX(COM.cmd_date), '%Y%m'), DATE_FORMAT(NOW(), '%Y%m')) > @mois
      )
    GROUP BY CLI.cli_id
    La requête est inversé au niveau des dates (sinon on a des valeurs négatives) :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    SELECT CLI.cli_id
    FROM clients CLI
      LEFT JOIN commandes COM
        ON COM.cli_id = CLI.cli_id
    WHERE
      PERIOD_DIFF(DATE_FORMAT(NOW(), '%Y%m'), DATE_FORMAT(CLI.cli_date, '%Y%m')) > @mois
      AND (
        MAX(COM.cmd_date) IS NULL
        OR
        PERIOD_DIFF(DATE_FORMAT(NOW(), '%Y%m'), DATE_FORMAT(MAX(COM.cmd_date), '%Y%m')) > @mois
      )
    GROUP BY CLI.cli_id
    Par contre j'ai une erreur sur le GROUP BY qui refuse si on ajoute la deuxième condition dans le where :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
      AND (
        MAX(COM.cmd_date) IS NULL
        OR
        PERIOD_DIFF(DATE_FORMAT(NOW(), '%Y%m'), DATE_FORMAT(MAX(COM.cmd_date), '%Y%m')) > @mois
      )
    Pouvez me dire pourquoi on ne peut pas renseigner la deuxième partie et quel serait la solution ?

    En faisant une requête simple sans cette deuxième conditions le retour met plus de 6 secondes pour 1000 clients et 10 000 commandes

    J'ai pensé à faire plutôt une jointure par double select qui est instantanée (c'est peut être une piste) :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    SELECT CLI.cli_id
    FROM clients CLI, commandes COM
    WHERE
      PERIOD_DIFF(DATE_FORMAT(NOW(), '%Y%m'), DATE_FORMAT(CLI.cli_date, '%Y%m')) > @mois
    AND COM.cmd_cli_id = CLI.cli_id
    GROUP BY CLI.cli_id

    Merci à Swoög et Alexandre pour leur aide.

  8. #8
    Expert éminent
    Avatar de Swoög
    Profil pro
    Inscrit en
    Janvier 2003
    Messages
    6 045
    Détails du profil
    Informations personnelles :
    Âge : 37
    Localisation : France

    Informations forums :
    Inscription : Janvier 2003
    Messages : 6 045
    Points : 8 339
    Points
    8 339
    Par défaut
    effectivement...

    la dexième partie du WHERE utilise des clause regroupantes (MAX) qui utilisent le résultat du GROUP BY...

    il faudrait le mettre dans un HAVING :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    SELECT CLI.cli_id
    FROM clients CLI
      LEFT JOIN commandes COM
        ON COM.cli_id = CLI.cli_id
    WHERE
      PERIOD_DIFF(DATE_FORMAT(CLI.cli_date, '%Y%m'), DATE_FORMAT(NOW(), '%Y%m')) > @mois
    GROUP BY CLI.cli_id
    HAVING
     MAX(COM.cmd_date) IS NULL
     OR
     PERIOD_DIFF(DATE_FORMAT(MAX(COM.cmd_date), '%Y%m'), DATE_FORMAT(NOW(), '%Y%m')) > @mois
    ensuite, pour le temps d'exécution, j'ai pas d'idée, désolé...

  9. #9
    Nouveau membre du Club
    Profil pro
    Développeur Web
    Inscrit en
    Septembre 2003
    Messages
    30
    Détails du profil
    Informations personnelles :
    Âge : 50
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Développeur Web

    Informations forums :
    Inscription : Septembre 2003
    Messages : 30
    Points : 26
    Points
    26
    Par défaut
    Je préfère un double select pour la jointure, puisqu'elle est instantanée à la différence du left join.
    Seulement je ne récupère pas les clients qui n'ont jamais commandés.

    J'ai repris une partie de ta requête :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    SELECT CLI.cli_id, CLI.cli_date, COM.cmd_date
    FROM clients CLI, commandes COM
    WHERE
      PERIOD_DIFF(DATE_FORMAT(NOW(), '%Y%m'), DATE_FORMAT(CLI.cmd_date, '%Y%m')) > @mois
    AND COM.cmd_cli_id = CLI.cli_id
    GROUP BY CLI.cli_id
    HAVING
     MAX(COM.cmd_date) IS NULL
     OR
     PERIOD_DIFF(DATE_FORMAT(NOW(), '%Y%m'),DATE_FORMAT(MAX(COM.cmd_date) , '%Y%m')) > @mois
    Est-ce possible de garder cette base et d'ajouter les clients n'ayant jamais commandés sans alourdir ?

  10. #10
    Expert éminent
    Avatar de Swoög
    Profil pro
    Inscrit en
    Janvier 2003
    Messages
    6 045
    Détails du profil
    Informations personnelles :
    Âge : 37
    Localisation : France

    Informations forums :
    Inscription : Janvier 2003
    Messages : 6 045
    Points : 8 339
    Points
    8 339
    Par défaut
    avec une requête externe, tu aura tous les clients...

    De plus les reuqêtes directes sont déconseillées, ne serait-ce que d'un point de vue sémantique...

    pour plus de renseignements, je t'invite à te pencher sur le tuto de SQLpro (un lien est dispo sur mon site)

Discussions similaires

  1. requete(client n'ayant pas de commande)
    Par aykima dans le forum Requêtes
    Réponses: 1
    Dernier message: 22/09/2012, 12h38
  2. Réponses: 1
    Dernier message: 01/12/2010, 15h12
  3. Réponses: 2
    Dernier message: 30/09/2009, 22h09
  4. Réponses: 7
    Dernier message: 27/08/2008, 12h53
  5. Emetteurs n'ayant pas envoyé de message depuis plus d'1 an
    Par emccbo dans le forum Requêtes et SQL.
    Réponses: 2
    Dernier message: 23/08/2007, 15h36

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo