Page 1 sur 1

Extraire des données a partir de 2 table

Posté : 05 juin 2008, 17:17
par Binarios
Bonjour
j'ai deux table ( avec 2clés Salle_id, Patient_ID dans chaque table) , comment faire pour creer une requette sql que retourne seulement les enregisterment de la table 1 et que ne sont pas dans la table 2,
NB les deux enregistrement egaux ont la meme Patient_iD et Salle_id
et merci d'avance

Posté : 05 juin 2008, 17:54
par ouckileou

Posté : 06 juin 2008, 14:29
par binarios
merci pour cette page,
mais moi j'ai deux table, et deux clé dans chaque table
par exemple
table1(cle1,cle2,champsX.....)
table2(cle1,cle2,champsY.....)

table1 : eng1, eng2, eng3
table2 : eng1, eng2,

requette doit retourner le eng 3

Posté : 06 juin 2008, 15:20
par ouckileou
Dans l'autre sujet aussi il y a 2 tables, une seule clé certes mais ça n'est pas bien compliqué à adapter...

Je recible le lien : http://www.phpfrance.com/forums/voir_re ... php#245370 (directement sur le bon sujet)

Posté : 06 juin 2008, 16:09
par Invité
je croix pas avec le deux clé c un peu difficle, 'ai essaye avec NOt in mais ca marche pas

Posté : 06 juin 2008, 16:20
par ouckileou
Mais pourquoi tu parles de NOT IN ? tu as regardé la requête de l'autre sujet au moins ?

Normalement tu as juste la jointure et le filtre à modifier, lui le fait sur 1 colonne, toi sur 2 :

Code : Tout sélectionner

SELECT t1.salle_id, t1.patient_id FROM table1 AS t1 LEFT OUTER JOIN table2 AS t2 ON t1.salle_id = t2.salle_id AND t1.patient_id = t2.patient_id WHERE t1.salle_id IS NULL AND t1.patient_id IS NULL;

Posté : 09 juin 2008, 11:26
par caroube
j'ai deux table ( avec 2clés Salle_id, Patient_ID dans chaque table) , comment faire pour creer une requette sql que retourne seulement les enregisterment de la table 1 et que ne sont pas dans la table 2
Faisons simple d'abord avec une seule clé :
1) Les enregistrements qui sont dans la table 1 --> ça retourne une liste

Code : Tout sélectionner

select id from table1 ...
2) Les enregistrements de la table 2 qui ne sont pas dans la liste de la table 1

Code : Tout sélectionner

select * from table2 where id not in (select id from table1 ...)
Ton problème est que tu n'as pas une seule clé, mais deux clés. Donc comment transformer 2 clés en 1 seule. Tout simplement en les concaténant. Si ce sont des clés textes, pas de problème et si ce sont des clés numériques variant par exemple entre 0 et 100000, tu multiplies la première par 1 milliard (pour avoir beaucoup de marge) et tu ajoutes la seconde

Code : Tout sélectionner

select * from table2 where (id1*1000000000+id2) not in (select id1*1000000000+id2 from table1 ...)

Posté : 09 juin 2008, 11:54
par ouckileou
C'est pas un peu tarabiscotée comme solution ? :roll:

Une jointure sur 2 colonnes ça marche...

Posté : 09 juin 2008, 12:19
par ouckileou
Bon pour être sûr j'ai fait des tests :

Code : Tout sélectionner

CREATE TABLE `tests`.`table1` ( `cle1` TINYINT( 2 ) UNSIGNED NOT NULL , `cle2` TINYINT( 2 ) UNSIGNED NOT NULL , `libelle` VARCHAR( 50 ) NOT NULL , PRIMARY KEY ( `cle1` , `cle2` ) ) ENGINE = InnoDB CREATE TABLE `tests`.`table2` ( `cle1` TINYINT( 2 ) UNSIGNED NOT NULL , `cle2` TINYINT( 2 ) UNSIGNED NOT NULL , `libelle` VARCHAR( 50 ) NOT NULL , PRIMARY KEY ( `cle1` , `cle2` ) ) ENGINE = InnoDB INSERT INTO table1 (cle1, cle2, libelle) VALUES (1, 1, 'enregistrement 1 - présent dans les 2 tables'); INSERT INTO table1 (cle1, cle2, libelle) VALUES (2, 2, 'enregistrement 2 - présent dans les 2 tables'); INSERT INTO table1 (cle1, cle2, libelle) VALUES (3, 3, 'enregistrement 3 - présent dans les 2 tables'); INSERT INTO table1 (cle1, cle2, libelle) VALUES (4, 4, 'enregistrement 4 - présent dans table 1 uniquement'); INSERT INTO table1 (cle1, cle2, libelle) VALUES (5, 5, 'enregistrement 5 - présent dans table 1 uniquement'); INSERT INTO table1 (cle1, cle2, libelle) VALUES (6, 6, 'enregistrement 6 - présent dans les 2 tables'); INSERT INTO table2 (cle1, cle2, libelle) VALUES (1, 1, 'enregistrement 1 - présent dans les 2 tables'); INSERT INTO table2 (cle1, cle2, libelle) VALUES (2, 2, 'enregistrement 2 - présent dans les 2 tables'); INSERT INTO table2 (cle1, cle2, libelle) VALUES (3, 3, 'enregistrement 3 - présent dans les 2 tables'); INSERT INTO table2 (cle1, cle2, libelle) VALUES (6, 6, 'enregistrement 6 - présent dans les 2 tables');
On récupère toutes les lignes :

Code : Tout sélectionner

SELECT t1.cle1, t1.cle2, t2.cle1, t2.cle2, t1.libelle FROM table1 AS t1 LEFT OUTER JOIN table2 AS t2 ON t1.cle1 = t2.cle1 AND t1.cle2 = t2.cle2
Résultat :

Code : Tout sélectionner

cle1 cle2 cle1 cle2 libelle 1 1 1 1 enregistrement 1 - présent dans les 2 tables 2 2 2 2 enregistrement 2 - présent dans les 2 tables 3 3 3 3 enregistrement 3 - présent dans les 2 tables 4 4 NULL NULL enregistrement 4 - présent dans table 1 uniquement 5 5 NULL NULL enregistrement 5 - présent dans table 1 uniquement 6 6 6 6 enregistrement 6 - présent dans les 2 tables
Et maintenant que celles qui ne sont pas dans la table 2 :

Code : Tout sélectionner

SELECT t1.cle1, t1.cle2, t2.cle1, t2.cle2, t1.libelle FROM table1 AS t1 LEFT OUTER JOIN table2 AS t2 ON t1.cle1 = t2.cle1 AND t1.cle2 = t2.cle2 WHERE t2.cle1 IS NULL AND t2.cle2 IS NULL
Résultat :

Code : Tout sélectionner

cle1 cle2 cle1 cle2 libelle 4 4 NULL NULL enregistrement 4 - présent dans table 1 uniquement 5 5 NULL NULL enregistrement 5 - présent dans table 1 uniquement

Posté : 09 juin 2008, 18:38
par caroube
C'est pas un peu tarabiscotée comme solution ? :roll:
Je ne sais pas.
Cela n'a sûrement pas l'élégance d'un OUTER JOIN à colonnes nulles, mais personnellement je trouve cela simple et compréhensible. Et en plus, c'est une "généralisation" du NOT IN sur une seule colonne. Et ça peut servir dans pas mal de cas comme des recherches de doublons sur plusieurs colonnes.
Mais il n'y a pas qu'une seule solution à un problème, donc chacun fait comme il se sent le mieux.

Posté : 09 juin 2008, 20:00
par zeus
Au delà de l'envie de l'utiliser, j'ai dans l'idée que la solution d'ouckileou est beaucoup plus optimisée. :-k

Je tenterais bien quelques benchmark pour vérifier ça, appuyé d'EXPLAIN PLAN. J'ai dans l'idée que, comme la solution de caroube agit sur les valeurs, il n'y a aucun index d'utilisé, donc aucun performance.
Mais j'attends de tester pour voir.

Posté : 09 juin 2008, 20:57
par Cyrano
...la solution d'ouckileou est beaucoup plus optimisée...
J'y vois personnellement une excellente base de tuto sur ce genre de requête :-k

Posté : 09 juin 2008, 23:06
par albat
Ouckileou++; :pouce:

Posté : 14 juin 2008, 14:21
par ouckileou
Ce n'est pas une question d'élégance, ça fait une requête au lieu d'une. Mais surtout ce qui me gêne, c'est ta manipulation avec multiplication/concaténation des clés, à la place d'une double jointure qui marche aussi bien.


Par contre pour un tuto ça me paraît un peu léger comme contenu quand même, je ne vois pas ce qu'on pourrait dire de plus en fait. À la rigueur dans la FAQ (mais bon elle est un peu chargée dans la config actuelle, il faudrait attendre une catégorisation)