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 de requête SELECT


Sujet :

Langage SQL

  1. #1
    Membre expérimenté

    Profil pro
    Inscrit en
    Avril 2004
    Messages
    219
    Détails du profil
    Informations personnelles :
    Âge : 42
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations forums :
    Inscription : Avril 2004
    Messages : 219
    Points : 1 655
    Points
    1 655
    Par défaut Optimisation de requête SELECT
    Bonjour ma problématiquement SQL simplifiée est la suivante :
    Je souhaite récupérer tous les tuples d'une table qui ont la valeur 0 ou 2 du champ C3. Par contre, pour 2 tuples avec la même valeur C1, et avec l'un ayant une valeur du champ C3 à 0 et l'autre à 2, je souhaiterai ne récupérer que celle avec la valeur 2. Tous les champs de la table doivent être retournés.
    Ci-dessous un exemple concret :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    T_TEST
    C1 C2 C3
    1 1 0
    1 2 2
    2 3 0
    4 4 3
    La clé primaire de la table est : C1, C2.
    Le champ C2 est unique fonctionnellement.

    La requête doit retourner le résultat suivant :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    C1 C2 C3
    1 2 2
    2 3 0
    La requête qui me permet de trouver ce résultat est la suivante. Je me pose la question de : peut-on l'optimiser pour éviter le "not in" ?
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    SELECT t.C1, t.C2, t.C3
    FROM T_TEST t
    WHERE t.C3 = 2
     
    UNION
     
    SELECT t1.C1, t1.C2, t1.C3
    FROM T_TEST t1
    WHERE t1.C3 = 0 
    AND t1.C1 not in (
       SELECT t2.C1 
       FROM T_TEST t2 
       WHERE t2.C3=2
    );

  2. #2
    Expert éminent
    Avatar de StringBuilder
    Homme Profil pro
    Chef de projets
    Inscrit en
    Février 2010
    Messages
    4 154
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 45
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Chef de projets
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Février 2010
    Messages : 4 154
    Points : 7 403
    Points
    7 403
    Billets dans le blog
    1
    Par défaut
    Code sql : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    select c1, c2, max(c3)
    from test
    where c3 in (0, 2)
    group by c1, c2

    Non ?
    On ne jouit bien que de ce qu’on partage.

  3. #3
    Expert éminent
    Avatar de StringBuilder
    Homme Profil pro
    Chef de projets
    Inscrit en
    Février 2010
    Messages
    4 154
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 45
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Chef de projets
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Février 2010
    Messages : 4 154
    Points : 7 403
    Points
    7 403
    Billets dans le blog
    1
    Par défaut
    Quoique non, tu peux avoir :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    c1 c2 c3
    1   1   0
    1   2   2
    => Et à ce moment, les deux lignes sont retournées... alors que tu ne veux que la seconde...

    Code sql : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     
    SELECT c1, c2, c3
    from test
    where (c1, c3) in (
    SELECT c1, max(c3)
    FROM test
    WHERE c3 IN (0, 2)
    GROUP BY c1)

    Ça devrait marcher.
    On ne jouit bien que de ce qu’on partage.

  4. #4
    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
    Citation Envoyé par TheSeb Voir le message
    La clé primaire de la table est : C1, C2.
    Le champ C2 est unique.
    Est-ce que C2 peut prendre la valeur NULL ? Si non, vous avez un problème de modélisation.

    Pour votre problème, quel est votre SGBD ?

  5. #5
    Membre expérimenté

    Profil pro
    Inscrit en
    Avril 2004
    Messages
    219
    Détails du profil
    Informations personnelles :
    Âge : 42
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations forums :
    Inscription : Avril 2004
    Messages : 219
    Points : 1 655
    Points
    1 655
    Par défaut
    Merci StringBuilder pour ta réponse, je vais regarder de plus près cette requête et étuudier si ça convient.

    Est-ce que C2 peut prendre la valeur NULL ? Si non, vous avez un problème de modélisation.

    Pour votre problème, quel est votre SGBD ?
    C2 ne peut pas être NULL. J'aurai dû préciser qu'il est unique fonctionnellement. La base de donnée n'ajoute pas cette contrainte. C'était juste une précision au cas où cela aurait pu aider à optimiser la requête. Je corriger le premier post.

    Le SGBD que j'utilise est Oracle.

  6. #6
    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
    Je l'aurai fait comme ceci :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    With T_TEST as
    (
    select 1 as c1, 1 as c2, 0 as c3 from dual union all
    select 1      , 2      , 2       from dual union all
    select 2      , 3      , 0       from dual union all
    select 4      , 4      , 3       from dual union all
    select 5      , 5      , 2       from dual union all
    select 6      , 6      , null    from dual
    )
      ,  SR as
    (
      select C1, C2, C3
           , row_number() over(partition by C1 order by case c3 when 2 then 0 when 0 then 1 else 2 end asc) as rn
        from T_TEST
    )
    select C1, C2, C3
      from SR
     where C3 in (0, 2)
       and RN = 1;
     
    C1 C2 C3
    -- -- --
     1  2  2 
     2  3  0 
     5  5  2
    Ou comme cela, c'est même surement plus rapide :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    WITH T_TEST AS
    (
    SELECT 1 AS c1, 1 AS c2, 0 AS c3 FROM dual union ALL
    SELECT 1      , 2      , 2       FROM dual union ALL
    SELECT 2      , 3      , 0       FROM dual union ALL
    SELECT 4      , 4      , 3       FROM dual union ALL
    SELECT 5      , 5      , 2       FROM dual union ALL
    SELECT 6      , 6      , NULL    FROM dual
    )
      select c1
           , max(c2) keep (dense_rank first order by c3 desc) as c2
           , max(c3)                                          as c3
        from T_TEST
       where c3 in (0, 2)
    group by c1;
     
    C1 C2 C3
    -- -- --
     1  2  2 
     2  3  0 
     5  5  2

  7. #7
    Membre expérimenté

    Profil pro
    Inscrit en
    Avril 2004
    Messages
    219
    Détails du profil
    Informations personnelles :
    Âge : 42
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations forums :
    Inscription : Avril 2004
    Messages : 219
    Points : 1 655
    Points
    1 655
    Par défaut
    Merci Waldar, j'ai testé la seconde requête que tu proposes, elle est nickel.

    Merci à tous pour vos réponses si rapide.

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

Discussions similaires

  1. Réponses: 3
    Dernier message: 10/10/2013, 11h47
  2. optimiser une requête SELECT
    Par molesqualeux dans le forum Requêtes
    Réponses: 3
    Dernier message: 18/02/2011, 15h11
  3. Optimisation d'une requête SELECT
    Par orus8 dans le forum Langage SQL
    Réponses: 2
    Dernier message: 19/10/2007, 10h08
  4. Optimisation de requêtes SQL - utilisation de IN SELECT
    Par cfeltz dans le forum Langage SQL
    Réponses: 3
    Dernier message: 20/12/2006, 09h28
  5. Optimisations mysql sur les requêtes SELECT: index
    Par leo'z dans le forum Débuter
    Réponses: 2
    Dernier message: 29/11/2003, 13h23

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