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

Développement SQL Server Discussion :

[TSQL] Optimiser une requête contenant des sous requêtes


Sujet :

Développement SQL Server

  1. #1
    Membre du Club
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Mars 2017
    Messages
    176
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 41
    Localisation : France, Gironde (Aquitaine)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Conseil

    Informations forums :
    Inscription : Mars 2017
    Messages : 176
    Points : 58
    Points
    58
    Par défaut [TSQL] Optimiser une requête contenant des sous requêtes
    Bonjour,

    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
    26
    27
    28
    29
    select count(distinct C.FID) AS C from
    (
    select distinct a.NUM, a.EID, a.FID, a.TP as TP1, b.TP as TP2, a.TVD as TVD1, b.TVD as TVD2
    from
    (select distinct 
    t6.ID as EID, t4.NUM, t1.ID, t1.SMI, t1.RVD, t2.TSI, t3.TP, t3.TVD, t2.FID
    from TABLE1 t1
    inner join TABLE2 t2 on t1.SMI = t2.ID
    inner join TABLE3 t3 on t1.RVD = t3.ID
    inner join TABLE4 t4 on t2.FID = t4.ID
    inner join TABLE5 t5 on t4.SSI = t5.ID
    left join TABLE6 t6 on t6.ID = t5.EID 
    where t2.TSI = 0
    ) a
    full join
    (select distinct 
    t6.ID as EID, t4.NUM, t1.ID, t1.SMI, t1.RVD, t2.TSI, t3.TP, t3.TVD, t2.FID
    from TABLE1 t1
    inner join TABLE2 t2 on t1.SMI = t2.ID
    inner join TABLE3 t3 on t1.RVD = t3.ID
    inner join TABLE4 t4 on t2.FID = t4.ID
    inner join TABLE5 t5 on t4.SSI = t5.ID
    left join TABLE6 t6 on t6.ID = t5.EID 
    where t2.TSI = 1
    ) b
    on a.EID = b.EID and a.FID = b.FID 
    where a.TP = b.TP and a.RVD <> b.RVD
     
    ) AS C WHERE C.EID = 1234
    La requête ci-dessus me permet de compter tous les FID en vérifiant que les TP de la vue a sont présents dans la vue b et que leur RVD sont différents.

    Cependant, je voudrais pouvoir modifier ma requête afin de comptabiliser aussi les FID de la vue a dont les TP n'ont pas de correspondance dans la vue b
    et les FID de la vue b dont les TP n'ont pas de correspondance dans la vue a.


    Cordialement,

  2. #2
    Modérateur

    Profil pro
    dba
    Inscrit en
    Janvier 2010
    Messages
    5 643
    Détails du profil
    Informations personnelles :
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : dba

    Informations forums :
    Inscription : Janvier 2010
    Messages : 5 643
    Points : 13 092
    Points
    13 092
    Par défaut
    Bonjour,

    remontez votre condition de filtre dans la condition de jointure externe et faites le COUNT sur les différentes tables (COUNT de comptabilise pas les NULL)

  3. #3
    Membre du Club
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Mars 2017
    Messages
    176
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 41
    Localisation : France, Gironde (Aquitaine)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Conseil

    Informations forums :
    Inscription : Mars 2017
    Messages : 176
    Points : 58
    Points
    58
    Par défaut
    Citation Envoyé par aieeeuuuuu Voir le message
    Bonjour,

    remontez votre condition de filtre dans la condition de jointure externe et faites le [c]COUNT(/c] sur les différentes tables (COUNT de comptabilise pas les NULL)
    Merci pour votre réponse.

    Je n'ai pas compris ce que vous voulez dire par
    remontez votre condition de filtre dans la condition de jointure externe
    et faites le [c]COUNT(/c] sur les différentes tables (COUNT de comptabilise pas les NULL)

  4. #4
    Modérateur

    Profil pro
    dba
    Inscrit en
    Janvier 2010
    Messages
    5 643
    Détails du profil
    Informations personnelles :
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : dba

    Informations forums :
    Inscription : Janvier 2010
    Messages : 5 643
    Points : 13 092
    Points
    13 092
    Par défaut
    remplacer
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    on a.EID = b.EID and a.FID = b.FID 
    where a.TP = b.TP and a.RVD <> b.RVD
    Par

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    on a.EID = b.EID and a.FID = b.FID 
    AND a.TP = b.TP and a.RVD <> b.RVD

  5. #5
    Membre du Club
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Mars 2017
    Messages
    176
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 41
    Localisation : France, Gironde (Aquitaine)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Conseil

    Informations forums :
    Inscription : Mars 2017
    Messages : 176
    Points : 58
    Points
    58
    Par défaut
    Merci pour votre réponse et votre réactivité.

    Votre solution n'a pas fonctionné.

    Cependant, j'ai rajouté une 3ème sous requête qui m'a donné un résultat proche de ce que j'attends mais il y a encore des FID qui ne sont pas comptabilisés :

    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
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    select count(distinct C.FID) AS C from
    (
    select distinct a.NUM, a.EID, a.FID, a.TP as TP1, b.TP as TP2, a.TVD as TVD1, b.TVD as TVD2
    from
    (select distinct 
    t6.ID as EID, t4.NUM, t1.ID, t1.SMI, t1.RVD, t2.TSI, t3.TP, t3.TVD, t2.FID
    from TABLE1 t1
    inner join TABLE2 t2 on t1.SMI = t2.ID
    inner join TABLE3 t3 on t1.RVD = t3.ID
    inner join TABLE4 t4 on t2.FID = t4.ID
    inner join TABLE5 t5 on t4.SSI = t5.ID
    left join TABLE6 t6 on t6.ID = t5.EID 
    where t2.TSI = 0
    ) a
    full join
    (select distinct 
    t6.ID as EID, t4.NUM, t1.ID, t1.SMI, t1.RVD, t2.TSI, t3.TP, t3.TVD, t2.FID
    from TABLE1 t1
    inner join TABLE2 t2 on t1.SMI = t2.ID
    inner join TABLE3 t3 on t1.RVD = t3.ID
    inner join TABLE4 t4 on t2.FID = t4.ID
    inner join TABLE5 t5 on t4.SSI = t5.ID
    left join TABLE6 t6 on t6.ID = t5.EID 
    where t2.TSI = 1
    ) b
    left join
    (select distinct 
    t6.ID as EID, t4.NUM, t1.ID, t1.SMI, t1.RVD, t2.TSI, t3.TP, t3.TVD, t2.FID
    from TABLE1 t1
    inner join TABLE2 t2 on t1.SMI = t2.ID
    inner join TABLE3 t3 on t1.RVD = t3.ID
    inner join TABLE4 t4 on t2.FID = t4.ID
    inner join TABLE5 t5 on t4.SSI = t5.ID
    left join TABLE6 t6 on t6.ID = t5.EID 
    where t2.TSI = 1
    ) c
    on a.EID = b.EID and a.FID = b.FID 
    where a.TP = b.TP and a.RVD <> b.RVD
    or (c.TP is null and b.TP is not null)
     
    ) AS C WHERE C.EID = 1234
    Peut-être qu'il faudrait rajouter une 4ème sous requête en faisant un right join ?

  6. #6
    Modérateur

    Profil pro
    dba
    Inscrit en
    Janvier 2010
    Messages
    5 643
    Détails du profil
    Informations personnelles :
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : dba

    Informations forums :
    Inscription : Janvier 2010
    Messages : 5 643
    Points : 13 092
    Points
    13 092
    Par défaut
    En fait, je pense que vous pouvez même vous passer de toutes ces jointures.

    Avec un GROUP BY et quelques CASE, vous devriez obtenir ce que vous voulez, mais je n'ai pas compris précisément le besoin...
    un jeu d'essai avec résultat attendu aiderait surement à mieux comprendre.

  7. #7
    Membre du Club
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Mars 2017
    Messages
    176
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 41
    Localisation : France, Gironde (Aquitaine)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Conseil

    Informations forums :
    Inscription : Mars 2017
    Messages : 176
    Points : 58
    Points
    58
    Par défaut
    Citation Envoyé par aieeeuuuuu Voir le message
    En fait, je pense que vous pouvez même vous passer de toutes ces jointures.

    Avec un GROUP BY et quelques CASE, vous devriez obtenir ce que vous voulez, mais je n'ai pas compris précisément le besoin...
    un jeu d'essai avec résultat attendu aiderait surement à mieux comprendre.
    Je voudrais ramener tous les enregistrements où l'on trouve une correspondance entre la vue a

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    select distinct 
    t6.ID as EID, t4.NUM, t1.ID, t1.SMI, t1.RVD, t2.TSI, t3.TP, t3.TVD, t2.FID
    from TABLE1 t1
    inner join TABLE2 t2 on t1.SMI = t2.ID
    inner join TABLE3 t3 on t1.RVD = t3.ID
    inner join TABLE4 t4 on t2.FID = t4.ID
    inner join TABLE5 t5 on t4.SSI = t5.ID
    left join TABLE6 t6 on t6.ID = t5.EID 
    where t2.TSI = 0
    et b

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    select distinct 
    t6.ID as EID, t4.NUM, t1.ID, t1.SMI, t1.RVD, t2.TSI, t3.TP, t3.TVD, t2.FID
    from TABLE1 t1
    inner join TABLE2 t2 on t1.SMI = t2.ID
    inner join TABLE3 t3 on t1.RVD = t3.ID
    inner join TABLE4 t4 on t2.FID = t4.ID
    inner join TABLE5 t5 on t4.SSI = t5.ID
    left join TABLE6 t6 on t6.ID = t5.EID 
    where t2.TSI = 1
    en faisant la jointure suivante (clé : a.EID = b.EID and a.FID = b.FID ) :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    on a.EID = b.EID and a.FID = b.FID 
    where a.TP = b.TP and a.RVD <> b.RVD
    On va appeler EID = dossier, FID = factures, TSI = catégorie, TP = options et RVD = prix. Donc je voudrais compter dans un premier toutes les factures appartenant à un même dossier et ayant les mêmes options () et dont le prix de ces options diffère ( > ce cas fonctionne déjà).

    Néanmoins, ce que je voudrais en plus c'est de pouvoir comptabiliser celles dont les options de la vue a n'existent pas dans la vue b et inversement.

    Merci,

  8. #8
    Membre du Club
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Mars 2017
    Messages
    176
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 41
    Localisation : France, Gironde (Aquitaine)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Conseil

    Informations forums :
    Inscription : Mars 2017
    Messages : 176
    Points : 58
    Points
    58
    Par défaut
    Citation Envoyé par aieeeuuuuu Voir le message
    En fait, je pense que vous pouvez même vous passer de toutes ces jointures.

    Avec un GROUP BY et quelques CASE, vous devriez obtenir ce que vous voulez, mais je n'ai pas compris précisément le besoin...
    un jeu d'essai avec résultat attendu aiderait surement à mieux comprendre.
    ci-joint une image contenant 4 tableaux de données et parmi ces 4 tableaux seuls les FID : 121212, 343434 et 787878 doivent être comptabilisés mais ma requête ne prend pas en compte le FID 343434.

    Nom : data.png
Affichages : 153
Taille : 116,9 Ko

    Merci.

  9. #9
    Expert confirmé
    Profil pro
    Inscrit en
    Août 2008
    Messages
    2 947
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2008
    Messages : 2 947
    Points : 5 846
    Points
    5 846
    Par défaut
    Pas sûr de bien comprendre, surtout les 4 tableaux excel.

    Ce ne serait pas :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    select ...
      from a
      full join b 
        on a.EID = b.EID 
       and a.FID = b.FID 
     where (a.TP = b.TP and a.RVD <> b.RVD) -- Mêmes options, pas le même prix
        or a.tp is null -- Options que dans B
        or b.tp is null -- Options que dans A

  10. #10
    Membre du Club
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Mars 2017
    Messages
    176
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 41
    Localisation : France, Gironde (Aquitaine)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Conseil

    Informations forums :
    Inscription : Mars 2017
    Messages : 176
    Points : 58
    Points
    58
    Par défaut
    Merci pour votre solution mais ça ne fonctionne pas.

    • Pour le premier tableau à gauche, c'est OK car on nous avons au moins un TP dont le RVD a changé pour le TSI 0 et 1.
      Donc pas besoin de vérifier s'il y a des TPs au niveau du TSI = 1 qui ne sont pas au niveau du TSI = 0 ou inversement.
    • Dans le tableau haut à droite, le FID doit être pris en compte car, même si les valeurs des RVD n'ont pas changé pour les différents TP trouvés dans TSI 0 et 1,
      on trouve néanmoins un TP de plus (ou de moins) dans un TSI par rapport à un autre.
      C'est ce cas qui n'est pas pris en compte dans ma requête.
    • Dans le tableau bas à gauche, on ne le prend pas en compte car on n'a aucun TP dans TSI 0 qui existe dans TSI 1.
    • Dans le tableau bas à droite c'est comme pour le premier tableau.



    En rajoutant un left joint dans la requête, j'obtiens un résultat proche de ce que j'attends mais il y a quelque chose qui n'est pas prise en compte dans ma requête que je n'arrive pas à voir (peut être qu'il faut rajouter une 4ème sous requête avec un right joint ??? ):

    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
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    select count(distinct C.FID) AS C from
    (
    select distinct a.NUM, a.EID, a.FID, a.TP as TP1, b.TP as TP2, a.TVD as TVD1, b.TVD as TVD2
    from
    (select distinct 
    t6.ID as EID, t4.NUM, t1.ID, t1.SMI, t1.RVD, t2.TSI, t3.TP, t3.TVD, t2.FID
    from TABLE1 t1
    inner join TABLE2 t2 on t1.SMI = t2.ID
    inner join TABLE3 t3 on t1.RVD = t3.ID
    inner join TABLE4 t4 on t2.FID = t4.ID
    inner join TABLE5 t5 on t4.SSI = t5.ID
    left join TABLE6 t6 on t6.ID = t5.EID 
    where t2.TSI = 0
    ) a
    full join
    (select distinct 
    t6.ID as EID, t4.NUM, t1.ID, t1.SMI, t1.RVD, t2.TSI, t3.TP, t3.TVD, t2.FID
    from TABLE1 t1
    inner join TABLE2 t2 on t1.SMI = t2.ID
    inner join TABLE3 t3 on t1.RVD = t3.ID
    inner join TABLE4 t4 on t2.FID = t4.ID
    inner join TABLE5 t5 on t4.SSI = t5.ID
    left join TABLE6 t6 on t6.ID = t5.EID 
    where t2.TSI = 1
    ) b
    left join
    (select distinct 
    t6.ID as EID, t4.NUM, t1.ID, t1.SMI, t1.RVD, t2.TSI, t3.TP, t3.TVD, t2.FID
    from TABLE1 t1
    inner join TABLE2 t2 on t1.SMI = t2.ID
    inner join TABLE3 t3 on t1.RVD = t3.ID
    inner join TABLE4 t4 on t2.FID = t4.ID
    inner join TABLE5 t5 on t4.SSI = t5.ID
    left join TABLE6 t6 on t6.ID = t5.EID 
    where t2.TSI = 1
    ) c
    on a.EID = b.EID and a.FID = b.FID 
    where a.TP = b.TP and a.RVD <> b.RVD
    or (c.TP is null and b.TP is not null)
     
    ) AS C WHERE C.EID = 1234

  11. #11
    Modérateur

    Profil pro
    dba
    Inscrit en
    Janvier 2010
    Messages
    5 643
    Détails du profil
    Informations personnelles :
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : dba

    Informations forums :
    Inscription : Janvier 2010
    Messages : 5 643
    Points : 13 092
    Points
    13 092
    Par défaut
    il manque une condition de jointure dans cette dernière requête...


    et pour ma part, je n'arrive toujours pas a comprendre précisément le besoin

  12. #12
    Invité
    Invité(e)
    Par défaut
    C'est sûr que lorsqu'on lance des acronymes sans explication, ce n'est pas des plus explicites...
    J'ai fait un effort pour FID : https://fr.wikipedia.org/wiki/FID mais ça ne semble pas correspondre.
    Et pour RVD, je me retrouve là : https://fr.wikipedia.org/wiki/Rob_Van_Dam

  13. #13
    Expert confirmé
    Profil pro
    Inscrit en
    Août 2008
    Messages
    2 947
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2008
    Messages : 2 947
    Points : 5 846
    Points
    5 846
    Par défaut
    Je pensais à quelque chose comme (sans sous-requête C):
    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
    26
    27
    28
    29
    30
    with a as (
    select distinct t6.ID as EID, t4.NUM, t1.ID, t1.SMI, t1.RVD, t2.TSI, t3.TP, t3.TVD, t2.FID
      from TABLE1 t1
     inner join TABLE2 t2 on t1.SMI = t2.ID
     inner join TABLE3 t3 on t1.RVD = t3.ID
     inner join TABLE4 t4 on t2.FID = t4.ID
     inner join TABLE5 t5 on t4.SSI = t5.ID
      left join TABLE6 t6 on t6.ID = t5.EID 
     where t2.TSI = 0
    ),
         b as (
    select distinct t6.ID as EID, t4.NUM, t1.ID, t1.SMI, t1.RVD, t2.TSI, t3.TP, t3.TVD, t2.FID
      from TABLE1 t1
     inner join TABLE2 t2 on t1.SMI = t2.ID
     inner join TABLE3 t3 on t1.RVD = t3.ID
     inner join TABLE4 t4 on t2.FID = t4.ID
     inner join TABLE5 t5 on t4.SSI = t5.ID
      left join TABLE6 t6 on t6.ID = t5.EID 
     where t2.TSI = 1
    )
    select a.*, b.*
      from a
      full join b 
        on a.EID = b.EID 
       and a.FID = b.FID 
     where a.eid = 1234
       and (  (a.TP = b.TP and a.RVD <> b.RVD) -- Mêmes options, pas le même prix
            or a.tp is null -- Options que dans B
            or b.tp is null -- Options que dans A
           )
    Je ne sais pas si ça répond au besoin, une capture d'écran n'est pas pratique à exploiter pour générer un jeu de test.

  14. #14
    Membre du Club
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Mars 2017
    Messages
    176
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 41
    Localisation : France, Gironde (Aquitaine)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Conseil

    Informations forums :
    Inscription : Mars 2017
    Messages : 176
    Points : 58
    Points
    58
    Par défaut
    Bonjour merci pour votre réponse mais ce n'est pas le résultat que j'attends.

    Ci-joint des scripts sql permettant de créer une table et insérer les données.

    table.txt, data1.txt, data2.txt, data3.txt

    Je m'attends à ce que la requête me retourne les num (2, 6, 14, 24, 27, 28, 32, 34, 46, 57, 62, 68)
    ou 12 en faisant un count (num0).

    Faire un select sur la table en faisant un order by 2,4 pour avoir l'aperçu qu'il faut afin de mieux comprendre le jeu de données.

  15. #15
    Expert confirmé
    Profil pro
    Inscrit en
    Août 2008
    Messages
    2 947
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2008
    Messages : 2 947
    Points : 5 846
    Points
    5 846
    Par défaut
    J'ai l'impression que s'il n'y a aucun FID (ou num) présent dans TSI1 alors on ne les sélectionne pas.
    Cette requête semble répondre au besoin, à voir si vous arrivez à l'adapter, j'ai reproduit les CTE A et B pour que ça corresponde mieux au début du post :
    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 b as (
    select eid1 as eid, num1 as num, fid1 as fid, tp1 as tp, rvd1 as rvd, tsi1 as tsi
      from TBL_TMP 
     where eid1=1234 
       and tsi1= 1
    ),
           a as (
    select eid0 as eid, num0 as num, fid0 as fid, tp0 as tp, rvd0 as rvd, tsi0 as tsi
      from TBL_TMP 
     where eid0=1234 
       and tsi0= 0
       and fid0 in (select b.fid from b)
    )
    select distinct coalesce(a.num, b.num)
      from a
      full join b 
        on a.EID = b.EID 
       and a.FID = b.FID 
       and a.num = b.num
       and a.TP = b.TP    
     where 1 = 1   
       and (  (a.RVD <> b.RVD) -- Mêmes options, pas le même prix
            or a.rvd is null -- Options que dans B
            or b.rvd is null -- Options que dans A
           );
    Sinon c'est aussi possible de jouer avec des UNION et EXCEPT.

  16. #16
    Membre du Club
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Mars 2017
    Messages
    176
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 41
    Localisation : France, Gironde (Aquitaine)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Conseil

    Informations forums :
    Inscription : Mars 2017
    Messages : 176
    Points : 58
    Points
    58
    Par défaut
    Merci beaucoup pour la solution proposée.

    ça a bien fonctionné pour les cas que je n'arrivais pas à gérer.
    Cependant, pour le cas où on a les memes options et pas le meme prix ça ne fonctionne plus.

    Ci-joint trois autres fichiers de données à insérer dans la table.
    data5.txt, data6.txt, data4.txt

    pour EID = 1234 avec le code proposé je trouve bien 12
    pour EID = 5000 je m'attends à trouver 13 (1,2,11,14,18,26,28,29,34,40,45,54,55)
    pour EID = 91011 je m'attends à trouver 8 (1,12,25,34,37,59,68,71)

  17. #17
    Expert confirmé
    Profil pro
    Inscrit en
    Août 2008
    Messages
    2 947
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2008
    Messages : 2 947
    Points : 5 846
    Points
    5 846
    Par défaut
    Je trouve bien les valeurs mentionnées :

    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
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    SQL>   with b as (
    select eid1 as eid, num1 as num, fid1 as fid, tp1 as tp, rvd1 as rvd, tsi1 as tsi
      from TBL_TMP
     where eid1=91011
       and tsi1= 1
    ),
           a as (
    select eid0 as eid, num0 as num, fid0 as fid, tp0 as tp, rvd0 as rvd, tsi0 as tsi
      from TBL_TMP
     where eid0=91011
       and tsi0= 0
       and fid0 in (select b.fid from b)
    )
    select distinct coalesce(a.num, b.num)
      from a
      full join b
        on a.EID = b.EID
       and a.FID = b.FID
       and a.num = b.num
       and a.TP = b.TP
     where 1 = 1
       and (  (a.RVD <> b.RVD) -- Mêmes options, pas le même prix
            or a.rvd is null -- Options que dans B
            or b.rvd is null -- Options que dans A
           ); 
     
    COALESCE(A.NUM,B.NUM)
    ---------------------
                        1
                       12
                       25
                       34
                       37
                       59
                       68
                       71
     
    8 ligne(s) selectionnee(s).
     
    SQL>
    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
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    SQL>   with b as (
    select eid1 as eid, num1 as num, fid1 as fid, tp1 as tp, rvd1 as rvd, tsi1 as tsi
      from TBL_TMP
     where eid1=5000
       and tsi1= 1
    ),
           a as (
    select eid0 as eid, num0 as num, fid0 as fid, tp0 as tp, rvd0 as rvd, tsi0 as tsi
      from TBL_TMP
     where eid0=5000
       and tsi0= 0
       and fid0 in (select b.fid from b)
    )
    select distinct coalesce(a.num, b.num)
      from a
      full join b
        on a.EID = b.EID
       and a.FID = b.FID
       and a.num = b.num
       and a.TP = b.TP
     where 1 = 1
       and (  (a.RVD <> b.RVD) -- Mêmes options, pas le même prix
            or a.rvd is null -- Options que dans B
            or b.rvd is null -- Options que dans A
           );
     
    COALESCE(A.NUM,B.NUM)
    ---------------------
                        1
                        2
                       11
                       14
                       18
                       26
                       28
                       29
                       34
                       40
                       45
                       54
                       55
     
    13 ligne(s) selectionnee(s).
     
    SQL>

  18. #18
    Membre du Club
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Mars 2017
    Messages
    176
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 41
    Localisation : France, Gironde (Aquitaine)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Conseil

    Informations forums :
    Inscription : Mars 2017
    Messages : 176
    Points : 58
    Points
    58
    Par défaut
    ça fonctionne bien avec la structure de la table TBL_TMP.

    Je ne sais pas si j'aurai du créer la table de cette manière (avec des colonnes doublées ex: EID0 et EID1 ....)
    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
    26
    27
    28
    insert into TBL_TMP (EID0, NUM0, FID0, TP0, RVD0, TSI0, EID1, NUM1, FID1, TP1, RVD1, TSI1
    select * from (select distinct 
    t6.ID as EID, t4.NUM, t1.ID, t3.TP, t1.RVD, t2.TSI
    from
    (select distinct 
    t6.ID as EID, t4.NUM, t1.ID, t1.SMI, t1.RVD, t2.TSI, t3.TP, t3.TVD, t2.FID
    from TABLE1 t1
    inner join TABLE2 t2 on t1.SMI = t2.ID
    inner join TABLE3 t3 on t1.RVD = t3.ID
    inner join TABLE4 t4 on t2.FID = t4.ID
    inner join TABLE5 t5 on t4.SSI = t5.ID
    left join TABLE6 t6 on t6.ID = t5.EID 
    where t2.TSI = 0 and t6.ID = 5000
    ) a
    full join
    (select distinct 
    t6.ID as EID, t4.NUM, t1.ID, t1.SMI, t1.RVD, t2.TSI, t3.TP, t3.TVD, t2.FID
    from TABLE1 t1
    inner join TABLE2 t2 on t1.SMI = t2.ID
    inner join TABLE3 t3 on t1.RVD = t3.ID
    inner join TABLE4 t4 on t2.FID = t4.ID
    inner join TABLE5 t5 on t4.SSI = t5.ID
    left join TABLE6 t6 on t6.ID = t5.EID 
    where t2.TSI = 1 and t6.ID = 5000
    and 
    ) b
    on a.EID = b.EID and a.NUM = b.NUM and a.TP = b.TP
    order by 2,4
    car quand j'exécute votre solution avec ma requête initiale

    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
    with b as (
    select distinct 
    t6.ID as EID, t4.NUM, t1.ID, t1.SMI, t1.RVD, t2.TSI, t3.TP, t3.TVD, t2.FID
    from TABLE1 t1
    inner join TABLE2 t2 on t1.SMI = t2.ID
    inner join TABLE3 t3 on t1.RVD = t3.ID
    inner join TABLE4 t4 on t2.FID = t4.ID
    inner join TABLE5 t5 on t4.SSI = t5.ID
    left join TABLE6 t6 on t6.ID = t5.EID 
    where t2.TSI = 1 and t6.ID = 5000
    ),
    a as (
    select distinct 
    t6.ID as EID, t4.NUM, t1.ID, t1.SMI, t1.RVD, t2.TSI, t3.TP, t3.TVD, t2.FID
    from TABLE1 t1
    inner join TABLE2 t2 on t1.SMI = t2.ID
    inner join TABLE3 t3 on t1.RVD = t3.ID
    inner join TABLE4 t4 on t2.FID = t4.ID
    inner join TABLE5 t5 on t4.SSI = t5.ID
    left join TABLE6 t6 on t6.ID = t5.EID 
    where t2.TSI = 0 and t6.ID = 5000
    and fp.ID not in (select b.FID from b)
    )
    .....
    ça ne fonctionne pas

  19. #19
    Expert confirmé
    Profil pro
    Inscrit en
    Août 2008
    Messages
    2 947
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2008
    Messages : 2 947
    Points : 5 846
    Points
    5 846
    Par défaut
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    and fp.ID not in (select b.FID from b)
    C'est une coquille dans le post ? Car dans ma requête c'est IN et pas NOT IN.

    Par ailleurs, à voir si c'est l'origine du problème ou pas, mais vous utilisez une jointure externe sur TABLE6, qui est ensuite filtré dans la clause WHERE sur l'ID.
    Cette jointure externe correspond donc finalement à une jointure interne. Vérifiez qu'il ne vous manque pas de données qui vous intéresse après le filtre.
    Si le filtre est bon, transformez le LEFT JOIN en INNER JOIN.

  20. #20
    Membre du Club
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Mars 2017
    Messages
    176
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 41
    Localisation : France, Gironde (Aquitaine)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Conseil

    Informations forums :
    Inscription : Mars 2017
    Messages : 176
    Points : 58
    Points
    58
    Par défaut
    Merci beaucoup.

    J'ai remplacé le LEFT JOIN par le INNER JOIN et ça a fonctionné.

+ Répondre à la discussion
Cette discussion est résolue.
Page 1 sur 2 12 DernièreDernière

Discussions similaires

  1. [9.5] Requête de selection dans une table contenant des redondances
    Par ghassen_khalil dans le forum Requêtes
    Réponses: 2
    Dernier message: 14/06/2016, 13h59
  2. optimisation d'une vue avec plusieurs sous-requêtes
    Par jean62 dans le forum Développement
    Réponses: 7
    Dernier message: 08/08/2012, 15h29
  3. Utiliser une jointure ou des sous-requêtes
    Par seabs dans le forum Langage SQL
    Réponses: 2
    Dernier message: 20/03/2011, 21h02
  4. Optimisation d'une requête contenant des sous-requêtes
    Par Christophe Charron dans le forum Requêtes
    Réponses: 2
    Dernier message: 28/06/2010, 15h34
  5. Afficher des sous-requêtes dans une requête
    Par ZashOne dans le forum Sql*Plus
    Réponses: 6
    Dernier message: 16/04/2008, 10h07

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