Précédent   Forum des professionnels en informatique > Bases de données > Firebird > SQL
SQL Forum d'entraide sur le SQL pour Firebird
Partagez cette discussion sur d'autres réseaux sociaux : Viadeo Twitter Google Facebook Digg Delicious MySpace Yahoo
Réponse Proposer ce sujet en actualité
 
Outils de la discussion
Publicité
'
Vieux 14/06/2005, 11h13   #1
Invité de passage
 
Inscription : avril 2005
Messages : 3
Détails du profil
Informations forums :
Inscription : avril 2005
Messages : 3
Points : 0
Points : 0
Par défaut Problème de perfs Sous requetes IN

Bonjour

Je vous explique mon probleme. J'ai 2 tables ou l'on stocke des donnees relatives à des comptes d'entreprises et qui schématiquement se présentent comme ceci (je ne donne que 3 champs par table sachant qu'elles en comportent une 40aine) :
Code:

Code :
1
2
3
4
 
 
Table1 :
Siret | Chiffre_d_affaires | Annee
Code :
1
2
3
 
Table2 :
Siret | Coef_de_perfs | Annee

Je souhaite faire une recherche dans les tables sur plusieures années.
La requête qui m'est venue à l'esprit est la suivante :
Code:

Code :
1
2
3
4
5
6
7
8
SELECT * FROM Table1 INNER JOIN Table2  ON Table1."SIRET"=Table2."SIRET" AND Table1."ANNEE"=Table2."ANNEE"
WHERE
((
(Table1."SIRET" IN (SELECT siret FROM table1 WHERE  chiffre_d_affaire < '9 000 000' AND annee=2001)) AND
(Table1."SIRET" IN (SELECT siret FROM table1 WHERE chiffre_d'affaire > '9 000 000' and annee=2002)) and
(Table1."SIRET" in (select siret from table2 where coef_de_perf > '6' and annee=2002))
) AND
(table1."ANNEE" = 2003));


Cette requête a pour but d'afficher les comptes de 2003 pour les entreprises qui ont eu un chiffre d'affaire < à 9 000 000 en 2001, > à 9 000 000 en 2002 et dont le coef de performances (contenu ds la Table2) est supérieur à 6 en 2002.

Cette requête fourni un résultat correct mais ma base étant immense (5 Go) elle est TRES lente.
Avez vous une requête plus rapide à me proposer ?
Au Secours
ias83 est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 14/06/2005, 16h17   #2
Membre Expert
 
Inscription : avril 2005
Messages : 1 672
Détails du profil
Informations forums :
Inscription : avril 2005
Messages : 1 672
Points : 1 337
Points : 1 337
tu as essayé avec une clause EXISTS qui est, en particulier, plus performant que la clause IN ?
Magnus est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 15/06/2005, 12h08   #3
Invité de passage
 
Inscription : avril 2005
Messages : 3
Détails du profil
Informations forums :
Inscription : avril 2005
Messages : 3
Points : 0
Points : 0
Merci pour ta réponse.

Le Exists est en effet plus rapide que le IN mais dans ce cas particulier je vois très mal comment construire une requête avec EXISTS qui fournisse un résultat correct sachant que :
Code :
1
2
3
4
5
6
7
8
9
 
SELECT * FROM Table1 INNER JOIN Table2  ON Table1."SIRET"=Table2."SIRET" AND Table1."ANNEE"=Table2."ANNEE" 
WHERE
((
( EXISTS (SELECT * FROM table1 INNER JOIN TABLE 2 ON ... WHERE  chiffre_d_affaire < '9 000 000' AND annee=2001))) AND
( EXISTS (SELECT * FROM table1 INNER JOIN TABLE 2 ON ... WHERE  chiffre_d_affaire > '9 000 000' AND annee=2002))) AND
(( EXISTS (SELECT * FROM table1 INNER JOIN TABLE 2 ON ... WHERE  coef_de_perf > '6' AND annee=2002)))
) AND
(table1."ANNEE" = 2003));

NE DONNE PAS UN RESULTAT CORRECT

HELP ?!?!
ias83 est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 15/06/2005, 12h34   #4
Membre Expert
 
Inscription : avril 2005
Messages : 1 672
Détails du profil
Informations forums :
Inscription : avril 2005
Messages : 1 672
Points : 1 337
Points : 1 337
Pourquoi tu utilises autant de parenthèses dans tes clauses :
Code :
1
2
3
4
5
6
SELECT * FROM Table1 INNER JOIN Table2  ON Table1."SIRET"=Table2."SIRET" AND Table1."ANNEE"=Table2."ANNEE" 
WHERE 
Table1."SIRET" IN (SELECT siret FROM table1 WHERE  chiffre_d_affaire < '9 000 000' AND annee=2001) AND 
Table1."SIRET" IN (SELECT siret FROM table1 WHERE chiffre_d'affaire > '9 000 000' and annee=2002) and 
Table1."SIRET" in (select siret from table2 where coef_de_perf > '6' and annee=2002)
AND table1."ANNEE" = 2003;
est équivalent et SURTOUT plus lisible que :
Code :
1
2
3
4
5
6
7
SELECT * FROM Table1 INNER JOIN Table2  ON Table1."SIRET"=Table2."SIRET" AND Table1."ANNEE"=Table2."ANNEE" 
WHERE 
(( 
(Table1."SIRET" IN (SELECT siret FROM table1 WHERE  chiffre_d_affaire < '9 000 000' AND annee=2001)) AND 
(Table1."SIRET" IN (SELECT siret FROM table1 WHERE chiffre_d'affaire > '9 000 000' and annee=2002)) and 
(Table1."SIRET" in (select siret from table2 where coef_de_perf > '6' and annee=2002)) 
) AND (table1."ANNEE" = 2003));
Au passage, tu dois pouvoir regrouper toutes tes sous-requêtes...

Bref, avec la clause EXISTS je ferais quelque chose comme ça :
Code :
1
2
3
4
5
6
7
8
SELECT *
FROM Table1 T1
  INNER JOIN Table2
  ON Table1."SIRET"=Table2."SIRET" AND Table1."ANNEE"=Table2."ANNEE" 
WHERE EXISTS (SELECT '+' FROM table1 tbl1 WHERE T1.Siret=tbl1.Siret AND ... AND chiffre_d_affaire < '9 000 000' AND annee=2001)
  AND EXISTS (SELECT '+' FROM table1 tbl1 WHERE T1.Siret=tbl1.Siret AND ... AND chiffre_d'affaire > '9 000 000' and annee=2002)
  and EXISTS (select '+' from table2 tbl2 WHERE T1.Siret=tbl2.Siret AND ...and coef_de_perf > '6' and annee=2002)
  AND table1."ANNEE" = 2003;
Qu'en penses-tu ?
Magnus est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 15/06/2005, 12h39   #5
Membre Expert
 
Inscription : avril 2005
Messages : 1 672
Détails du profil
Informations forums :
Inscription : avril 2005
Messages : 1 672
Points : 1 337
Points : 1 337
Je ne sais pas l'impact au niveau des performances mais tu dois pouvoir regrouper tes 2 premières sous-requêtes en faisant (sous réserve que le mot clé INTERSECT fonctionne) :
Code :
1
2
3
4
5
6
7
SELECT siret
FROM table1
WHERE chiffre_d_affaire < '9 000 000' AND annee=2001
INTERSECT
SELECT siret
FROM table1
WHERE chiffre_d'affaire > '9 000 000' and annee=2002
Magnus est déconnecté   Envoyer un message privé Réponse avec citation 00
Réponse Proposer ce sujet en actualité
Outils de la discussion



Fuseau horaire GMT +2. Il est actuellement 09h47.


 
 
 
 
Partenaires

Hébergement Web