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 :

Jointure avec critère variable


Sujet :

Langage SQL

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre averti
    Profil pro
    Inscrit en
    Septembre 2003
    Messages
    10
    Détails du profil
    Informations personnelles :
    Localisation : Canada

    Informations forums :
    Inscription : Septembre 2003
    Messages : 10
    Par défaut Jointure avec critère variable
    Bonjour,

    J'ai un problème pour composer une jointure sur des conditions variables avec Oracle.

    J'ai une table de résultats chimiques (près de 2 millions de lignes, exemple simplifié) pour des métaux, hydrocarbures, composés organiques, pesticides, etc.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    CREATE TABLE Resultat
    (chemical_name NVARCHAR2(255),
     valeur NUMBER(30,15))
     
    INSERT INTO Resultat (chemical_name, valeur) VALUES ('Plomb', 4)
    INSERT INTO Resultat (chemical_name, valeur) VALUES ('Plomb dissous', 58)
    INSERT INTO Resultat (chemical_name, valeur) VALUES ('Uranium', 0.5)
    INSERT INTO Resultat (chemical_name, valeur) VALUES ('Zinc', 9)
    INSERT INTO Resultat (chemical_name, valeur) VALUES ('Calcium dissous', 2541)
    J'ai aussi une table de critères pour valider les résultats (environ 300 lignes)

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    CREATE TABLE Critere
    (SUBSTANCE NVARCHAR2(255),
     Scenario_1 NUMBER(30,15),
     Scenario_2 NUMBER(30,15))
     
    INSERT INTO Critere (SUBSTANCE, Scenario_1, Scenario_2) VALUES ('Plomb', 5, 12)
    INSERT INTO Critere (SUBSTANCE, Scenario_1, Scenario_2) VALUES ('Plomb dissous', 8, 10)
    INSERT INTO Critere (SUBSTANCE, Scenario_1, Scenario_2) VALUES ('Zinc dissous', 15, 50)
    INSERT INTO Critere (SUBSTANCE, Scenario_1, Scenario_2) VALUES ('Calcium dissous', 2000, 5000)
    INSERT INTO Critere (SUBSTANCE, Scenario_1, Scenario_2) VALUES ('Nitrate', 10, 18)
    Je veux un affichage où chaque résultat est accolé à ses critères (si applicable) pour comparaison ultérieure.
    Tout ça fonctionne bien.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    SELECT chemical_name, valeur, substance, scenario_1, scenario_2 
    FROM Resultat 
    LEFT JOIN Critere 
    ON chemical_name = substance
     
    chemical_name	valeur	substance	scenario_1	scenario_2
    _____________	______	_________	__________	__________
    Plomb		4	Plomb		5		12
    Plomb dissous	58	Plomb dissous	8		10
    Uranium		0.5
    Zinc		9
    Calcium dissous	2541	Calcium dissous	2000		5000
    J'ai besoin de modifier cette requête pour traiter des conditions particulières. Si un métal n'a pas de critères mais que des critères existent pour la version dissoute, je veux faire cette jointure (voir l'exemple du zinc).

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    chemical_name	valeur	substance	scenario_1	scenario_2
    _____________	______	_________	__________	__________
    Plomb		4	Plomb		5		12
    Plomb dissous	58	Plomb dissous	8		10
    Uranium		0.5
    Zinc		9	Zinc dissous	15		50
    Calcium dissous	2541	Calcium dissous	2000		5000
    La requête qui s'en approche est :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    SELECT chemical_name, valeur, substance, scenario_1, scenario_2 
    FROM Resultat 
    LEFT JOIN Critere 
    ON ((chemical_name = substance) OR (chemical_name || ' dissous' = substance))
    mais certains résultats sont dédoublés (voir le plomb 4):

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    chemical_name	valeur	substance	scenario_1	scenario_2
    _____________	______	_________	__________	__________
    Plomb		4	Plomb		5		12
    Plomb 		4	Plomb dissous	8		10
    Plomb dissous	58	Plomb dissous	8		10
    Uranium		0.5
    Zinc		9	Zinc dissous	15		50
    Calcium dissous	2541	Calcium dissous	2000		5000

    Comment composer cette jointure sans dédoubler les résultats de plusieurs métaux ?

    Merci.
    Christian

  2. #2
    Membre régulier
    Profil pro
    Inscrit en
    Novembre 2008
    Messages
    13
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2008
    Messages : 13
    Par défaut
    Bonjour,

    Il faut résonner comme si tu le faisais "à la main":
    Pour chaque ligne de la table Resultat
    • Je cherche dans la table critere une ligne avec substance = chemical_name

    • Si je n'ai pas trouvé de ligne, je cherche dans la table critère une ligne avec substance = chemical_name suffixé par " dissous"



    Il faut donc faire 2 jointures gauches avec la table Critere, la 1ère sans ajouter "dissous" à chemical_name, la 2ème en ajoutant dissous
    Si la 1ère remonte des données tu les récupère sinon tu prend les données de la 2ème:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
     
    SELECT chemical_name, valeur
    	, CASE WHEN C1.substance IS NOT NULL THEN C1.substance ELSE C2.substance END AS substance
    	, CASE WHEN C1.substance IS NOT NULL THEN C1.scenario_1 ELSE C2.scenario_1 END AS scenario_1
    	, CASE WHEN C1.substance IS NOT NULL THEN C1.scenario_2 ELSE C2.scenario_2 END AS scenario_2
    FROM Resultat 
    LEFT JOIN Critere AS C1
    	ON chemical_name = C1.substance
    LEFT JOIN Critere AS C2
    	ON chemical_name || ' dissous' = C2.substance

  3. #3
    Modérateur
    Avatar de al1_24
    Homme Profil pro
    Retraité
    Inscrit en
    Mai 2002
    Messages
    9 136
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 64
    Localisation : France, Val de Marne (Île de France)

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

    Informations forums :
    Inscription : Mai 2002
    Messages : 9 136
    Par défaut
    Il faut en effet passer par deux étapes. D'abord le scénario qui correspond à la substance, ensuite celui de la substance dissoute SI le premier n'est pas trouvé :
    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
    SELECT  chemical_name, valeur, substance, scenario_1, scenario_2 
    FROM    Resultat 
        INNER JOIN
            Critere 
            ON  chemical_name = substance
    UNION ALL
    SELECT  chemical_name, valeur, substance, scenario_1, scenario_2 
    FROM    Resultat    AS  res 
        LEFT JOIN
            Critere     AS crt 
            ON  res.chemical_name || ' dissous' = crt.substance
    WHERE   NOT EXISTS
            (   SELECT  NULL 
                FROM    Critere AS  exc
                WHERE   res.chemical_name = exc.substance
            )
    Modérateur Langage SQL
    Règles du forum Langage SQL à lire par tous, N'hésitez pas à consulter les cours SQL
    N'oubliez pas le bouton et pensez aux balises
    [code]
    Si une réponse vous a aidé à résoudre votre problème, n'oubliez pas de voter pour elle en cliquant sur
    Aide-toi et le forum t'aidera : Un problème exposé sans mentionner les tentatives de résolution infructueuses peut laisser supposer que le posteur attend qu'on fasse son travail à sa place... et ne donne pas envie d'y répondre.

  4. #4
    Membre averti
    Profil pro
    Inscrit en
    Septembre 2003
    Messages
    10
    Détails du profil
    Informations personnelles :
    Localisation : Canada

    Informations forums :
    Inscription : Septembre 2003
    Messages : 10
    Par défaut
    La solution avec les CASE WHEN fonctionne à merveille, très lisible et facile à adapter pour un cas particulier que j'ai découvert en faisant les tests. J'avais exploré l'idée des CASE mais sans penser à joindre deux fois la même table. La seconde solution fonctionne aussi mais l'adaptation au cas particulier est plus compliquée.

    Dans les deux cas, il faut enlever les AS entre les noms des tables et les alias.

    Merci beaucoup à vous deux.

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

Discussions similaires

  1. [Toutes versions] SommeProd avec critères variables
    Par Kiouane dans le forum Macros et VBA Excel
    Réponses: 3
    Dernier message: 07/11/2016, 15h44
  2. [XL-2013] Créer des boucles avec critères variables
    Par Riquette1 dans le forum Macros et VBA Excel
    Réponses: 8
    Dernier message: 03/10/2016, 14h03
  3. [XL-2003] Supprimer lignes avec critères variables
    Par Vadorblanc dans le forum Macros et VBA Excel
    Réponses: 2
    Dernier message: 10/03/2011, 23h24
  4. Requête sur 2 tables avec critères de jointures particuliers
    Par Randomdev dans le forum Langage SQL
    Réponses: 3
    Dernier message: 20/01/2009, 18h00
  5. Suppression et Création table avec critère de variable
    Par stephanies_1977 dans le forum VBA Access
    Réponses: 4
    Dernier message: 12/03/2008, 13h53

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