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 : 49
    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 : 36
    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
    Rédacteur "éclectique" (XML, Cours PHP, Cours JavaScript, IRC, Web...)
    Les Règles du Forum - Mon Site Web sur DVP.com (Développement Web, PHP, (X)HTML/CSS, SQL, XML, IRC)
    je ne répondrai à aucune question technique via MP, MSN ou Skype : les Forums sont là pour ça !!! Merci de me demander avant de m'ajouter à vos contacts sinon je bloque !
    pensez à la balise [ code ] (bouton #) et au tag (en bas)

  3. #3
    Nouveau membre du Club
    Profil pro
    Développeur Web
    Inscrit en
    Septembre 2003
    Messages
    30
    Détails du profil
    Informations personnelles :
    Âge : 49
    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 : 47
    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.
    Alexandre Tranchant
    Chef de projet AMO pour le Cerema.
    Retrouvez mes articles sur PHP et Symfony

  5. #5
    Expert éminent
    Avatar de Swoög
    Profil pro
    Inscrit en
    Janvier 2003
    Messages
    6 045
    Détails du profil
    Informations personnelles :
    Âge : 36
    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
    Rédacteur "éclectique" (XML, Cours PHP, Cours JavaScript, IRC, Web...)
    Les Règles du Forum - Mon Site Web sur DVP.com (Développement Web, PHP, (X)HTML/CSS, SQL, XML, IRC)
    je ne répondrai à aucune question technique via MP, MSN ou Skype : les Forums sont là pour ça !!! Merci de me demander avant de m'ajouter à vos contacts sinon je bloque !
    pensez à la balise [ code ] (bouton #) et au tag (en bas)

  6. #6
    Nouveau membre du Club
    Profil pro
    Développeur Web
    Inscrit en
    Septembre 2003
    Messages
    30
    Détails du profil
    Informations personnelles :
    Âge : 49
    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 : 49
    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 : 36
    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é...
    Rédacteur "éclectique" (XML, Cours PHP, Cours JavaScript, IRC, Web...)
    Les Règles du Forum - Mon Site Web sur DVP.com (Développement Web, PHP, (X)HTML/CSS, SQL, XML, IRC)
    je ne répondrai à aucune question technique via MP, MSN ou Skype : les Forums sont là pour ça !!! Merci de me demander avant de m'ajouter à vos contacts sinon je bloque !
    pensez à la balise [ code ] (bouton #) et au tag (en bas)

  9. #9
    Nouveau membre du Club
    Profil pro
    Développeur Web
    Inscrit en
    Septembre 2003
    Messages
    30
    Détails du profil
    Informations personnelles :
    Âge : 49
    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 : 36
    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)
    Rédacteur "éclectique" (XML, Cours PHP, Cours JavaScript, IRC, Web...)
    Les Règles du Forum - Mon Site Web sur DVP.com (Développement Web, PHP, (X)HTML/CSS, SQL, XML, IRC)
    je ne répondrai à aucune question technique via MP, MSN ou Skype : les Forums sont là pour ça !!! Merci de me demander avant de m'ajouter à vos contacts sinon je bloque !
    pensez à la balise [ code ] (bouton #) et au tag (en bas)

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, 11h38
  2. Réponses: 1
    Dernier message: 01/12/2010, 14h12
  3. Réponses: 2
    Dernier message: 30/09/2009, 21h09
  4. Réponses: 7
    Dernier message: 27/08/2008, 11h53
  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, 14h36

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