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

Langage SQL Discussion :

[OPTIMISATION SQL] Comment enlever une sous-requête


Sujet :

Langage SQL

  1. #1
    Membre actif
    Profil pro
    Ingénieur développement
    Inscrit en
    Juillet 2004
    Messages
    323
    Détails du profil
    Informations personnelles :
    Localisation : France, Isère (Rhône Alpes)

    Informations professionnelles :
    Activité : Ingénieur développement

    Informations forums :
    Inscription : Juillet 2004
    Messages : 323
    Points : 291
    Points
    291
    Par défaut [OPTIMISATION SQL] Comment enlever une sous-requête
    J'ai 1 table de ce type commandes:
    id_commande (primary key) | id_client | date | total

    600 | 111 | 2007-01-04 | 50
    700 | 111 | 2008-01-03 | 60
    888 | 111 | 2009-01-02 | 40
    601 | 112 | 2007-01-04 | 30
    801 | 112 | 2009-01-04 | 10
    802 | 113 | 2009-04-04 | 100

    Je souhaite avoir le total des commandes de 2009 pour les clients ayant déjà commandé avant 2009. Je désire aussi le nombre de commande du même type, c'est à dire de 2009 mais avec une personne qui a déjà commandé avant 2009. Je veux aussi le nombre de client de la même façon donc qui a commandé en 2009 ET avant.

    Je fais donc une requête de ce type : (requête 1)
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    SELECT SUM(total) AS total, COUNT(DISTINCT id_commande) AS nb_cmd, COUNT(DISTINCT id_commande) AS nb_cmd
    FROM commandes
    WHERE date >= '2009-01-01'
    AND id_client IN (
    SELECT DISTINCT id_client
    FROM commandes
    WHERE date < '2009-01-01')
    Ceci fonctionne, je me demandais s'il existait un moyen de faire la même chose avec une seule requête. Résultat : 40+10 = 50

    J'ai essayé ça : (requête 2)
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    SELECT SUM(total) AS total, COUNT(DISTINCT id_commande) AS nb_cmd, COUNT(DISTINCT id_commande) AS nb_cmd
    FROM commandes c1
    JOIN commandes c2
    ON c1.id_client=c2.id_client AND
    c1.date >= '2009-01-01'
    AND c2.date < '2009-01-01'
    Mais le total est FAUX car la commande 888 est comptée 2 fois! 40+40+10
    Je pense qu'avec un GROUP BY, ce sera le même problème.

    Est-ce possible de réduire la requête 1 qui comprend une sous requête en UNE SEULE requête (sans sous requête)?

    Merci
    Хајде Јано коло да играмо

  2. #2
    Modérateur
    Avatar de Waldar
    Homme Profil pro
    Customer Success Manager @Vertica
    Inscrit en
    Septembre 2008
    Messages
    8 452
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 46
    Localisation : France, Val de Marne (Île de France)

    Informations professionnelles :
    Activité : Customer Success Manager @Vertica
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2008
    Messages : 8 452
    Points : 17 820
    Points
    17 820
    Par défaut
    Comme vous travaillez sur deux sous-ensembles différents (les clients ayant commandés avant 2009 et les commandes passées après 2009), je ne pense pas qu'il y ait une autre méthode que votre première requête.

    Le doublon dans votre seconde requête s'explique car votre client 111 a passé deux commandes avant 2009.

    Si vous tenez à la seconde écriture il faudra de toutes façon faire une requête qui ressemblera à votre IN (requête Oracle) :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    select
        sum(c1.total) as total
    from
        commandes c1
        inner join (select distinct id_client
                    from commandes
                    where dt_cmd < date '2009-01-01') c2
          on c2.id_client = c1.id_client
    where
        c1.dt_cmd >= date '2009-01-01'
    Attention, date est un mot réservé du SQL et vous ne devez pas l'utiliser comme nom de colonne.

  3. #3
    Membre actif
    Profil pro
    Ingénieur développement
    Inscrit en
    Juillet 2004
    Messages
    323
    Détails du profil
    Informations personnelles :
    Localisation : France, Isère (Rhône Alpes)

    Informations professionnelles :
    Activité : Ingénieur développement

    Informations forums :
    Inscription : Juillet 2004
    Messages : 323
    Points : 291
    Points
    291
    Par défaut
    ok, ça revient à peu près au même alors.

    Donc je vois que ce n'est pas simplifiable.
    Dommage.

    J'avais compris en effet pourquoi ma deuxième requête n'était pas bonne.

    Ok, merci, je crois que je vais mettre un "Résolu".
    Хајде Јано коло да играмо

  4. #4
    Rédacteur

    Avatar de SQLpro
    Homme Profil pro
    Expert bases de données / SQL / MS SQL Server / Postgresql
    Inscrit en
    Mai 2002
    Messages
    21 768
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Var (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Expert bases de données / SQL / MS SQL Server / Postgresql
    Secteur : Conseil

    Informations forums :
    Inscription : Mai 2002
    Messages : 21 768
    Points : 52 565
    Points
    52 565
    Billets dans le blog
    5
    Par défaut
    On peut faire cela en une seule requête à l'aide des fonctions de fenêtrage en précisant sur quelle partie se fait le comptage dans la clause OVER et voire avec la fenêtre de données.

    mais comme je n'ai pas compris ce que vous attendez.... Un exemple aurait été le bienvenu !

    A +
    Frédéric Brouard - SQLpro - ARCHITECTE DE DONNÉES - expert SGBDR et langage SQL
    Le site sur les SGBD relationnels et le langage SQL: http://sqlpro.developpez.com/
    Blog SQL, SQL Server, SGBDR : http://blog.developpez.com/sqlpro
    Expert Microsoft SQL Server - M.V.P. (Most valuable Professional) MS Corp.
    Entreprise SQL SPOT : modélisation, conseils, audit, optimisation, formation...
    * * * * * Expertise SQL Server : http://mssqlserver.fr/ * * * * *

  5. #5
    Membre actif
    Profil pro
    Ingénieur développement
    Inscrit en
    Juillet 2004
    Messages
    323
    Détails du profil
    Informations personnelles :
    Localisation : France, Isère (Rhône Alpes)

    Informations professionnelles :
    Activité : Ingénieur développement

    Informations forums :
    Inscription : Juillet 2004
    Messages : 323
    Points : 291
    Points
    291
    Par défaut
    C'est quoi les fonctions de fenétrages? Il y en a avec MySQL?

    En fait, j'avais la bonne requête mais je me demandais juste si on pouvais plus l'optimiser.
    Хајде Јано коло да играмо

  6. #6
    Rédacteur

    Avatar de SQLpro
    Homme Profil pro
    Expert bases de données / SQL / MS SQL Server / Postgresql
    Inscrit en
    Mai 2002
    Messages
    21 768
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Var (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Expert bases de données / SQL / MS SQL Server / Postgresql
    Secteur : Conseil

    Informations forums :
    Inscription : Mai 2002
    Messages : 21 768
    Points : 52 565
    Points
    52 565
    Billets dans le blog
    5
    Par défaut
    MySQL je ne pense pas. MySQL est très en retard niveau SQL...

    A +
    Frédéric Brouard - SQLpro - ARCHITECTE DE DONNÉES - expert SGBDR et langage SQL
    Le site sur les SGBD relationnels et le langage SQL: http://sqlpro.developpez.com/
    Blog SQL, SQL Server, SGBDR : http://blog.developpez.com/sqlpro
    Expert Microsoft SQL Server - M.V.P. (Most valuable Professional) MS Corp.
    Entreprise SQL SPOT : modélisation, conseils, audit, optimisation, formation...
    * * * * * Expertise SQL Server : http://mssqlserver.fr/ * * * * *

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Comment créer une sous requête sur plusieurs champs?
    Par Anonymouse dans le forum Requêtes et SQL.
    Réponses: 4
    Dernier message: 10/06/2008, 09h13
  2. Comment enlever une sous-chaine d'une chaine ?
    Par bigey3 dans le forum Langage
    Réponses: 8
    Dernier message: 17/12/2007, 17h23
  3. [SQL] Comment insérer une variable php dans une requête SQL ?
    Par Yagami_Raito dans le forum PHP & Base de données
    Réponses: 4
    Dernier message: 14/05/2007, 08h47
  4. comment faire une sous requête
    Par zope49 dans le forum BIRT
    Réponses: 1
    Dernier message: 18/12/2006, 17h41
  5. [SQL] Comment automatiser une requête SQL alimentée par un formulaire HTML?
    Par tse_tilky_moje_imja dans le forum PHP & Base de données
    Réponses: 3
    Dernier message: 29/06/2006, 23h46

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