2013-03-11 8 views
0

Qu'est-ce qui peut rendre ces deux requêtes différentes?SQL naturel Join et requête SELECT imbriquée

La poste est en effet principalement du code.

SELECT DISTINCT S.name 
FROM 
    student S NATURAL JOIN taking NATURAL JOIN 
    (select * from class where classnum ='121') 
WHERE 
    department='CMPSC' 
    AND semester='Spring 2013'; 



SELECT DISTINCT S.name 
FROM 
    student S NATURAL JOIN taking NATURAL JOIN class 
WHERE 
    department='CMPSC' 
    AND semester='Spring 2013' 
    AND classnum='121'; 

Merci!

EDIT:

En réponse à la demande d'expliquer la commande suivante: je devais le faire sur ORACLE, donc je ne sais pas si cela est le résultat attendu:

Ceci est la première requête:

Plan hash value: 3259400360 

------------------------------------------------------ 
| Id | Operation      | Name   | 
------------------------------------------------------ 
| 0 | SELECT STATEMENT    |    | 
| 1 | HASH UNIQUE     |    | 
| 2 | NESTED LOOPS    |    | 
| 3 | NESTED LOOPS    |    | 
| 4 |  TABLE ACCESS FULL   | CLASS  | 
| 5 |  INDEX FULL SCAN   | SYS_C0099014 | 
| 6 | TABLE ACCESS BY INDEX ROWID| STUDENT  | 
| 7 |  INDEX UNIQUE SCAN   | SYS_C0098998 | 
------------------------------------------------------ 

Predicate Information (identified by operation id): 
--------------------------------------------------- 

    4 - filter("CLASSNUM"=121 AND "CLASS"."SEMESTER"='Spring 2013' AND 
       "CLASS"."DEPARTMENT"='CMPSC') 

PLAN_TABLE_OUTPUT 
-------------------------------------------------------------------------------- 
    5 - access("TAKING"."SCHEDULENUM"="CLASS"."SCHEDULENUM" AND 
       "TAKING"."SEMESTER"='Spring 2013') 
     filter("TAKING"."SEMESTER"='Spring 2013' AND 
       "TAKING"."SCHEDULENUM"="CLASS"."SCHEDULENUM") 
    7 - access("S"."STUDENTNUM"="TAKING"."STUDENTNUM") 

Deuxième QUERY:

PLAN_TABLE_OUTPUT 
-------------------------------------------------------------------------------- 
Plan hash value: 226170808 

------------------------------------------------------- 
| Id | Operation      | Name   | 
------------------------------------------------------- 
| 0 | SELECT STATEMENT    |    | 
| 1 | HASH UNIQUE     |    | 
| 2 | HASH JOIN     |    | 
| 3 | MERGE JOIN     |    | 
| 4 |  TABLE ACCESS BY INDEX ROWID| STUDENT  | 
| 5 |  INDEX FULL SCAN   | SYS_C0098998 | 
| 6 |  SORT JOIN     |    | 
| 7 |  INDEX FULL SCAN   | SYS_C0099014 | 
| 8 | TABLE ACCESS FULL   | CLASS  | 
------------------------------------------------------- 

Predicate Information (identified by operation id): 
--------------------------------------------------- 

PLAN_TABLE_OUTPUT 
-------------------------------------------------------------------------------- 

    2 - access("TAKING"."SEMESTER"="CLASS"."SEMESTER") 
    6 - access("S"."STUDENTNUM"="TAKING"."STUDENTNUM") 
     filter("S"."STUDENTNUM"="TAKING"."STUDENTNUM") 
    7 - access("TAKING"."SEMESTER"='Spring 2013') 
     filter("TAKING"."SEMESTER"='Spring 2013') 
    8 - filter("CLASS"."CLASSNUM"=121 AND "CLASS"."SEMESTER"='Spring 2013' AND 
       "CLASS"."DEPARTMENT"='CMPSC') 
+1

Voulez-vous dire que les résultats sont différents ou la performance? Si les résultats sont différents, veuillez poster des exemples. –

+0

Essayez d'exécuter 'explain' sur les deux requêtes pour obtenir le plan d'exécution de la requête; comparez-les pour voir les différences. Postez-les également ici pour que les autres puissent les analyser. [Expliquer la syntaxe] (http://dev.mysql.com/doc/refman/5.0/en/explain.html) – Kshitij

+0

@Kshitij J'espère que c'est ce que vous avez demandé, je cours Oracle. – ammoun

Répondre

0

Si la performance est la question, il est beca utilisez-vous vaincre l'indexation. Lorsque la sous-requête est exécutée, le serveur peut utiliser des index pour récupérer les résultats; Toutefois, il ne peut pas indexer les résultats de la sous-requête, ce qui entraîne des performances moins bonnes. En règle générale, les tentatives de «déjouer» l'optimiseur ne fonctionnent pas bien - vous finirez soit par des requêtes plus difficiles à lire et faire exactement la même chose (l'optimiseur optimisera la requête à quelque chose d'identique à ce qu'il était à l'origine) se retrouver avec des cas comme celui-ci où la performance est pire. Les clauses JOIN doivent être utilisées pour définir la jointure, ne pas contraindre les données.

L'optimiseur exécute les requêtes suivantes identique:

SELECT * 
FROM foo f 
    JOIN bar b 
    ON f.id = b.id 
     AND b.col = 'baz' 

et

SELECT * 
FROM foo f 
    JOIN bar b 
    ON f.id = b.id 
WHERE b.col = 'baz' 

alors

SELECT * 
FROM foo f 
    JOIN (
    SELECT * 
    FROM bar b 
    WHERE col = 'baz' 
) AS b 
    ON f.id = b.id 

génère essentiellement une table temporaire non indexée en mémoire dans mysql. Il s'exécute de manière identique aux deux précédents dans le serveur sql.

+0

Ceci est très intéressant Michael, pourriez-vous regarder expliquer la sortie? – ammoun

+0

Il semble que SQL Server optimisera réellement les trois requêtes pour qu'elles soient identiques. MySQL, cependant, ne le fera pas. Regardez ces Fiddles SQL et cliquez sur 'View Execution Plan': [Requête SQL Fiddle # 1] (http://sqlfiddle.com/#!2/fd343/1), [Requête SQL Fiddle # 2] (http: // sqlfiddle.com/#!2/fd343/3), [Requête SQL Fiddle # 3] (http://sqlfiddle.com/#!2/fd343/2) –