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

SQL Oracle Discussion :

Requete SQL sur jointure test d'égalité et pas de contenance


Sujet :

SQL Oracle

  1. #1
    Membre du Club
    Inscrit en
    Juin 2007
    Messages
    58
    Détails du profil
    Informations personnelles :
    Âge : 51

    Informations forums :
    Inscription : Juin 2007
    Messages : 58
    Points : 59
    Points
    59
    Par défaut Requete SQL sur jointure test d'égalité et pas de contenance
    Le cas est le suivant :

    J'ai une table T3_TABLE_A2 et une jointure T3_JOIN_A2_A2 qui permet aux objets de la table T3_TABLE_A2 de pointer vers eux-mêmes.

    Auparavant il y avait 1 seul champ PK sur la table T3_TABLE_A2 donc je m'en sortais, mais maintenant il y a 2 PK et ca se complique grandement (pour moi).

    je veux les objets de T3_TABLE_A2 qui pointent (à travers la jointure)à vers un objet de T3_TABLE_A2 précis (0,0) ici pour simplifier.

    J'encode avec un moteur ainsi :
    Code sql : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
     
        select distinct T3_TABLE_A2.ID, T3_TABLE_A2.SITE_ID 
        from T3_TABLE_A2, T3_JOIN_A2_A2 
        where (((T3_JOIN_A2_A2.ID1=(T3_TABLE_A2.ID)) 
                and (T3_JOIN_A2_A2.SITE_ID1=(T3_TABLE_A2.SITE_ID))) 
                and ((T3_JOIN_A2_A2.ID2=0) 
                and (T3_JOIN_A2_A2.SITE_ID2=0)))

    Ca "marche" mais me retourne trop de résultats : cela retourne tous les T3_TABLE_A2 qui CONTIENNENT mon objet cible (0,0) mais pas qui sont en EGALITE avec cette cible. Ceux qui pointent vers la cible + d'autres valeurs sont aussi retournés (j'ai un filtre contient au lieu d'égale).

    Avec la double clé je ne vois pas trop comment faire : le code ci-dessous ne marche pas (aucun résultat) :
    Code sql : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
     
      select distinct T3_TABLE_A2.ID, T3_TABLE_A2.SITE_ID 
        from T3_TABLE_A2, T3_JOIN_A2_A2 
        where (((T3_JOIN_A2_A2.ID1=(T3_TABLE_A2.ID)) 
                and (T3_JOIN_A2_A2.SITE_ID1=(T3_TABLE_A2.SITE_ID))) 
                and ((T3_JOIN_A2_A2.ID2=0) 
                and (T3_JOIN_A2_A2.SITE_ID2=0))
                and not exists (select * 
        from T3_TABLE_A2, T3_JOIN_A2_A2 
        where (((T3_JOIN_A2_A2.ID1=(T3_TABLE_A2.ID)) 
                and (T3_JOIN_A2_A2.SITE_ID1=(T3_TABLE_A2.SITE_ID))) 
                and ((T3_JOIN_A2_A2.ID2<>0) 
                or (T3_JOIN_A2_A2.SITE_ID2<>0)))))

    avec une seule ID j'encodais ainsi :
    Code sql : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    select distinct T3_TABLE_A.ID from T3_TABLE_A where 
    (((ID in (select ID1 from T3_JOIN_A_A where (ID2=1))) and not exists (select ID1 from T3_JOIN_A_A LY_5 where (ID2<>1) and (ID=ID1))))
    et ca marchait

    Des idées ?
    Merci

  2. #2
    McM
    McM est déconnecté
    Expert éminent

    Homme Profil pro
    Développeur Oracle
    Inscrit en
    Juillet 2003
    Messages
    4 580
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Développeur Oracle

    Informations forums :
    Inscription : Juillet 2003
    Messages : 4 580
    Points : 7 740
    Points
    7 740
    Billets dans le blog
    4
    Par défaut
    C'est l'enfer ton code.. t'aime bien les parenthèses, non ?
    Un peu d'alias simplifierai aussi pas mal
    ton premier code:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    SELECT DISTINCT t.ID, t.site_id 
    FROM T3_TABLE_A2 t, T3_JOIN_A2_A2 j
    WHERE j.id1	= t.ID
    AND j.site_id1	= t.site_id
    AND j.id2	= 0
    AND j.site_id2	= 0
    peut être transformé en
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    SELECT ID, site_id
    FROM T3_TABLE_A2 t
    WHERE EXISTS ( SELECT 1 
    		FROM T3_JOIN_A2_A2 j	
    		WHERE j.id1	= t.ID
    		AND j.site_id1	= t.site_id
    		AND j.id2	= 0
    		AND j.site_id2	= 0
    	)
    Et je n'ai pas compris la finalité de ce que tu veux. Peux tu donner un exemple concret, car ta phrase
    (j'ai un filtre contient au lieu d'égale).
    , faudrait l'expliquer

  3. #3
    McM
    McM est déconnecté
    Expert éminent

    Homme Profil pro
    Développeur Oracle
    Inscrit en
    Juillet 2003
    Messages
    4 580
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Développeur Oracle

    Informations forums :
    Inscription : Juillet 2003
    Messages : 4 580
    Points : 7 740
    Points
    7 740
    Billets dans le blog
    4
    Par défaut
    Ta première requete peut être transformée en
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    SELECT id1 as id, site_id1 as site_id
    FROM T3_JOIN_A2_A2 	
    WHERE id2	= 0
    AND site_id2	= 0

  4. #4
    Membre du Club
    Inscrit en
    Juin 2007
    Messages
    58
    Détails du profil
    Informations personnelles :
    Âge : 51

    Informations forums :
    Inscription : Juin 2007
    Messages : 58
    Points : 59
    Points
    59
    Par défaut Suite
    1) Pour les parenthèses et les noms justement je ne les aime pas plus que cela : c'est que mon code génère la requête SQL à partir du modèle Java Objet.

    En passant en Modele Objet ca sera peut etre plus clair:

    Classe A a une relation multiple vers elle même
    (par exemple une personne connait des personnes ...)

    Si j'ai A1 --> A0 et A2 --> A0 et A1

    A1 pointe vers A0 seulement et A2 vers A0 ET vers A1 il y a donc une entrée dans la jointure pour A1 et 2 pour A2

    Je veux les A qui pointent EXACTEMENT vers A0 et A0 seulement (c'est ca que j'appelle un EGAL sur la relation) alors que A2 à une relation qui CONTIENT A0 mais n'est pas EGALE à A0 car il y a aussi A1.

    J'espere que c'est plus clair
    en tout cas merci pour votre réponse.

  5. #5
    McM
    McM est déconnecté
    Expert éminent

    Homme Profil pro
    Développeur Oracle
    Inscrit en
    Juillet 2003
    Messages
    4 580
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Développeur Oracle

    Informations forums :
    Inscription : Juillet 2003
    Messages : 4 580
    Points : 7 740
    Points
    7 740
    Billets dans le blog
    4
    Par défaut
    Beaucoup plus clair
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    SELECT id1 as id, site_id1 as site_id
    FROM T3_JOIN_A2_A2 	
    GROUP BY id1, site_id1
    HAVING count(*)  = 1
    AND min(id2)	= 0
    AND min(site_id2)	= 0

  6. #6
    Membre du Club
    Inscrit en
    Juin 2007
    Messages
    58
    Détails du profil
    Informations personnelles :
    Âge : 51

    Informations forums :
    Inscription : Juin 2007
    Messages : 58
    Points : 59
    Points
    59
    Par défaut Merci
    Je vais investiquer ce type de syntaxe avec having count() : le pb c'est que je suis aussi obligé de garder
    le SELECT DISTINCT T3_TABLE_A2.ID, T3_TABLE_A2.SITE_ID
    FROM T3_TABLE_A2, T3_JOIN_A2_A2
    car la requete porte sur T3_TABLE_A2.
    Je l'ai simplifiée pour la question mais je dois ramener des champs de T3_TABLE_A2 et j'ai potentiellement des criteres supplémentaires sur ces champs de T3_TABLE_A2 dans le where.

    C'est une interface graphique qui permet à l'utilisateur de saisir un filtre complexe ou simple sur le modele objet et je dois la transcrire en une requete ce qui marche à 99% sauf quelques détails dans ce genre.

  7. #7
    McM
    McM est déconnecté
    Expert éminent

    Homme Profil pro
    Développeur Oracle
    Inscrit en
    Juillet 2003
    Messages
    4 580
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Développeur Oracle

    Informations forums :
    Inscription : Juillet 2003
    Messages : 4 580
    Points : 7 740
    Points
    7 740
    Billets dans le blog
    4
    Par défaut
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    SELECT id, site_id
    FROM T3_TABLE_A2 
    WHERE (id, site_id) IN (SELECT id1, site_id1
    		FROM T3_JOIN_A2_A2 	
    		GROUP BY id1, site_id1
    		HAVING count(*)  = 1
    		AND min(id2)	= 0
    		AND min(site_id2)	= 0)
    J'ai corrigé le code précédent, un WHERE qui n'avait rien à faire là.

  8. #8
    McM
    McM est déconnecté
    Expert éminent

    Homme Profil pro
    Développeur Oracle
    Inscrit en
    Juillet 2003
    Messages
    4 580
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Développeur Oracle

    Informations forums :
    Inscription : Juillet 2003
    Messages : 4 580
    Points : 7 740
    Points
    7 740
    Billets dans le blog
    4
    Par défaut
    Pour info, tu peux le gérer aussi en MINUS (Attention il fait un distinct)
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    SELECT t.id, t.site_id 
    FROM T3_TABLE_A2 t, T3_JOIN_A2_A2 j
    WHERE j.id1	= t.ID
    AND j.site_id1	= t.site_id
    AND j.id2	= 0
    AND j.site_id2	= 0
    MINUS
    SELECT t.id, t.site_id 
    FROM T3_TABLE_A2 t, T3_JOIN_A2_A2 j
    WHERE j.id1	= t.ID
    AND j.site_id1	= t.site_id
    AND ( j.id2	<> 0
    OR j.site_id2	<> 0)

  9. #9
    Membre du Club
    Inscrit en
    Juin 2007
    Messages
    58
    Détails du profil
    Informations personnelles :
    Âge : 51

    Informations forums :
    Inscription : Juin 2007
    Messages : 58
    Points : 59
    Points
    59
    Par défaut MERCI
    Les deux requetes marchent effectivement !

    La première m'oblige à revoir davantage l'encodeur mais à le "bon goût" d'etre aussi valable sur oracle et MySql
    Le minus est plus simple car il s'ajoute juste à ma requete précédente sans 'casser' l'existant mais sous MySql il n'aime pas du tout le minus.
    En tout cas merci pour ces syntaxes !

  10. #10
    Membre du Club
    Inscrit en
    Juin 2007
    Messages
    58
    Détails du profil
    Informations personnelles :
    Âge : 51

    Informations forums :
    Inscription : Juin 2007
    Messages : 58
    Points : 59
    Points
    59
    Par défaut Complément pour Oracle et MySql
    Pour info j'ai aussi ca qui semble marcher sur Oracle et MySql avec un NOT IN au lieu d'un MINUS
    Code sql : 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.id, t.site_id 
    FROM T3_TABLE_A2 t, T3_JOIN_A2_A2 j
    WHERE j.id1	= t.ID
    AND j.site_id1	= t.site_id
    AND j.id2	= 0
    AND j.site_id2	= 0
    and (t.id, t.site_id) NOT IN (
    SELECT t.id, t.site_id 
    FROM T3_TABLE_A2 t, T3_JOIN_A2_A2 j
    WHERE j.id1	= t.ID
    AND j.site_id1	= t.site_id
    AND ( j.id2	<> 0
    OR j.site_id2	<> 0))

  11. #11
    McM
    McM est déconnecté
    Expert éminent

    Homme Profil pro
    Développeur Oracle
    Inscrit en
    Juillet 2003
    Messages
    4 580
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Développeur Oracle

    Informations forums :
    Inscription : Juillet 2003
    Messages : 4 580
    Points : 7 740
    Points
    7 740
    Billets dans le blog
    4
    Par défaut
    Préfère le NOT EXISTS au NOT IN (et ça t'enlève une jointure)
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    SELECT t.ID, t.site_id 
    FROM T3_TABLE_A2 t, T3_JOIN_A2_A2 j
    WHERE j.id1	= t.ID
    AND j.site_id1	= t.site_id
    AND j.id2	= 0
    AND j.site_id2	= 0
    AND NOT EXISTS (SELECT 1
    		FROM T3_JOIN_A2_A2 j2
    		WHERE j2.id1	= t.ID
    		AND j2.site_id1	= t.site_id
    		AND ( j2.id2	<> 0
    		OR j2.site_id2	<> 0))

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

Discussions similaires

  1. Requete SQL avec jointure sur trois tables
    Par pit2121 dans le forum Langage SQL
    Réponses: 1
    Dernier message: 19/05/2008, 23h07
  2. Requete SQL sur table dbase et date du jour
    Par Jean-François PETIT dans le forum Bases de données
    Réponses: 5
    Dernier message: 29/03/2005, 09h31
  3. Ecrire une requete SQL sur plusieurs lignes
    Par PrinceMaster77 dans le forum ASP
    Réponses: 2
    Dernier message: 15/11/2004, 14h47
  4. requete sql sur un grand nombre d enregistrement
    Par marielaure dans le forum Langage SQL
    Réponses: 5
    Dernier message: 13/08/2004, 11h53
  5. Réponses: 2
    Dernier message: 03/05/2004, 12h13

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