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

DB2 Discussion :

Renvoyer une seule ligne conditionnelle sur une jointure ?


Sujet :

DB2

  1. #1
    Membre régulier
    Profil pro
    Inscrit en
    Avril 2004
    Messages
    334
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2004
    Messages : 334
    Points : 123
    Points
    123
    Par défaut Renvoyer une seule ligne conditionnelle sur une jointure ?
    Bonjour,

    J'essaie sans succès de joindre 2 tables, une table de clients et une de compléments, ces tables sont reliées par le numéro client :



    Un client peut avoir plusieurs lignes identiques associées, à l'exception du numéro de téléphone qui peut être de plusieurs types différents (Fax, Domicile, Mobile…).

    Je souhaite lister :

    - tous les clients (l'intégralité de la table Clients)

    - s'il y a une correspondance avec la table Complements, associer leur adresse et :
    --------- s'ils disposent d'un numéro de Mobile afficher le numéro de Mobile seul et pas les autres lignes
    --------- sinon s'ils disposent d'un numéro de Domicile afficher le numéro de Domicile et pas les autres lignes
    --------- sinon (pas de numéro de téléphone du tout ou pas de numéro valide (autre que 'Mobile' ou 'Domicile')) n'afficher que l'adresse et une valeur par défaut pour le numéro de téléphone (NULL ou 'N' ou 'Non', à définir)

    - sinon (si pas de correspondance avec la table Complements), les valeurs 'Adresse', 'Type_telephone' et 'Telephone' ressortent à 'NULL' par le LEFT JOIN

    J'ai mis en vert les infos à afficher selon les différents cas de figure :



    On voit que le clients 170 n'a aucune correspondance dans la table des Complements.

    Et voici ce que j'attends en sélection finale :



    Ce dont je suis plus ou moins certain est que je dois passer par un 'Clients LEFT JOIN Complements' dans la mesure où je restitue les clients même s'ils n'ont aucune adresse ou numéro de téléphone.

    Pour le reste je ne sais pas si je peux faire ce que je veux faire dans un LEFT JOIN ou si je dois passer par une sous-requête et à ce moment comment la mettre en place. Je suis ouvert à toute bonne idée

    Merci beaucoup si vous pouvez m'aider, je me prends bien la tête sur cette problématique.

    C. Tobini

  2. #2
    Membre actif
    Inscrit en
    Juin 2008
    Messages
    154
    Détails du profil
    Informations personnelles :
    Âge : 57

    Informations forums :
    Inscription : Juin 2008
    Messages : 154
    Points : 225
    Points
    225
    Par défaut
    Bonsoir,

    Tu peux résoudre le problème en faisant une jointure externe + une sous-requête supplémentaire sur la table Complements pour vérifier qu'il n'existe pas une autre ligne plus importante que celle en cours pour le même ID. Le terme "plus importante" étant dépendant des règles de gestion que tu as définies.

    En terme de perf, cela ajoute un accès à Complements mais j'imagine qu'il y a un index sur NUM_CLIENT, donc pas trop de souci à prévoir.

    Cela donnerait la requête suivante

    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
    SELECT A.PRENOM, A.NOM, A.ID, B.ADRESSE,
    CASE
    WHEN B.TYPE_TELEPHONE = 'MOBILE' THEN B.TYPE_TELEPHONE
    WHEN B.TYPE_TELEPHONE = 'DOMICILE' THEN B.TYPE_TELEPHONE
    ELSE NULL
    END,
    CASE
    WHEN B.TYPE_TELEPHONE = 'MOBILE' THEN B.NUMERO
    WHEN B.TYPE_TELEPHONE = 'DOMICILE' THEN B.NUMERO
    ELSE NULL
    END
    FROM XXX.CLIENT A
    LEFT JOIN XXX.COMPLEMENTS B
    ON A.ID = B.NUM_CLIENT
    WHERE NOT EXISTS (
    SELECT 0
    FROM XXX.COMPLEMENTS C
    WHERE A.ID = C.NUM_CLIENT
    AND CASE
    WHEN C.TYPE_TELEPHONE = 'MOBILE' THEN '1'
    WHEN C.TYPE_TELEPHONE = 'DOMICILE' THEN '2'
    WHEN C.TYPE_TELEPHONE IS NULL THEN NULL
    ELSE '3'
    END
    <
    CASE
    WHEN B.TYPE_TELEPHONE = 'MOBILE' THEN '1'
    WHEN B.TYPE_TELEPHONE = 'DOMICILE' THEN '2'
    WHEN B.TYPE_TELEPHONE IS NULL THEN NULL
    ELSE '3'
    END
    )
    ;

  3. #3
    Expert confirmé
    Homme Profil pro
    Inscrit en
    Mai 2002
    Messages
    3 173
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 41
    Localisation : France, Rhône (Rhône Alpes)

    Informations forums :
    Inscription : Mai 2002
    Messages : 3 173
    Points : 5 345
    Points
    5 345
    Par défaut
    Bonjour,


    J'aurai une approche différente.

    => vous avez des problèmes de modélisation ce qui entraine une complication de votre requête.

    Votre type de téléphone doit être externalisé dans une autre entité, et vous devez ajouter un autre attribut qui va déterminer l'ordre d'importance des types de téléphones.

    MCD :
    Telephone-1,1------Possede-----0,n-Type_telephone

    MPD :
    Telephone(tel_id, #cli_id, #ttl_id, ...) => ici peut être que le couple cli_id / ttl_id peut faire office de clef primaire, tout dépend de votre fonctionnel
    Type_telephone(ttl_id, ttl_description, ttl_ordre, ....)


    Que vient faire l’adresse dans la table des téléphones ????
    En plus vous dupliquez des données => problème d'intégrité à un moment ou un autre !

    Il vous faut soit :
    - une autre table adresse (si plus d'une adresse par client possible)
    - remonter cet attribut dans votre table de client (si une seule adresse possible)



    A partir de là on part sur une utilisation soit d'une fonction de fenêtrage, soit de keep() (je ne sais pas si c'est implémenté sous DB2).
    De plus je part du principe que vous remontez l'adresse dans la table client :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
     
    with tmp as (
    select b.cli_id, c.ttl_description, b.tel_numero, row_number() over(partition by b.cli_id order by c.ttl_order ) as rnk
    from telephone b on a.id = b.cli_id
    inner join type_telephone c on b.ttl_id = c.ttl_id)
     
     
    select A.PRENOM, A.NOM, A.ID, A.ADRESSE, b.ttl_description, b.tel_numero
    from clients a
    left outer join tmp b on a.id = b.cliid and b.rnk = 1

  4. #4
    Membre éprouvé
    Profil pro
    Inscrit en
    Mai 2008
    Messages
    821
    Détails du profil
    Informations personnelles :
    Âge : 54
    Localisation : France, Hérault (Languedoc Roussillon)

    Informations forums :
    Inscription : Mai 2008
    Messages : 821
    Points : 1 084
    Points
    1 084
    Par défaut
    J'aurai aussi une approche différente :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    Select distinct c.*,                                                
    coalesce(m.Type_Telephone, d.Type_Telephone) Type    ,              
    coalesce(m.telephone     , d.telephone     ) Numero  ,              
    coalesce(m.Adresse , d.Adresse, a.Adresse  ) Adresse                
    from clients c                                                      
      left join complements m on                                        
       (m.Num_cli, m.Type_Telephone)=(id, 'Mobile')                     
      left join complements d on                                        
       (d.Num_cli, d.Type_Telephone)=(id, 'Domicile')                   
      left join complements a on                                        
       a.Num_cli = id and a.Type_Telephone not in ('Domicile', 'Mobile')

Discussions similaires

  1. Réponses: 1
    Dernier message: 08/01/2010, 13h46
  2. Réponses: 3
    Dernier message: 24/10/2008, 19h31
  3. Réponses: 2
    Dernier message: 22/10/2008, 17h53
  4. jointure qui retourne tout sur une seule ligne
    Par Ralfman68 dans le forum Requêtes
    Réponses: 9
    Dernier message: 12/10/2007, 21h52
  5. Afficher une chaîne de caractères sur une seule ligne?
    Par Antigonos Ier Gonatas dans le forum Général Python
    Réponses: 3
    Dernier message: 14/06/2006, 23h07

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