2012-06-20 11 views
6

J'ai une table disons table1 qui a 3 colonnes column1, column2 and column3.LEFT OUTER JOIN vs SUBSELECT dans MySQL

Les column1 et column2 sont un FOREIGN KEY avec 2 autres tables. Cependant, les données de column3 proviennent d'un nombre n de tables.

Par exemple. Laissez-nous considérer Facebook. Pour afficher les activités, il peut gérer une table qui peut contenir user1 photoliked photo1 ou user1 statusliked status1. Donc, dans ce cas column3 ne peut pas être un FOREIGN KEY avec une table spécifique.

Maintenant il y a 2 façons d'obtenir des données réelles -

1er chemin -

SELECT user_id, 
     verb_id, 
     CASE WHEN verb_id = photoliked THEN 
      (SELECT photo_name FROM photos WHERE photo_id = column3) -- getting the desired data from the third column 
     WHEN verb_id = statusliked THEN 
      (SELECT status FROM statustable WHERE status_id = column3) 
     ELSE '' END AS performedon 
FROM table1 
    JOIN table2 ON user_id = user_id -- joining the first column 
    JOIN table3 ON verb_id = verb_id -- joining the second column 

2ème chemin -

SELECT user_id, 
     verb_id, 
     CASE WHEN verb_id = photoliked THEN 
      p.photo_name 
     WHEN verb_id = statusliked THEN 
      s.status 
     ELSE '' END AS performedon 
FROM table1 
    JOIN table2 ON user_id = user_id -- joining the first column 
    JOIN table3 ON verb_id = verb_id -- joining the second column 
    LEFT JOIN photos p ON p.photo_id = column3 -- joining the column3 with specific table 
    LEFT JOIN statustable s ON s.status_id = column3 

Question

Lequel des 2 façons est préférable de récupérer des données? et laquelle des 2 requêtes est moins chère?

+0

possible dupliquer http://stackoverflow.com/a/10684539/1239506 –

+0

Non, il est pas double emploi. Dans cette question, il y a un 'IN' dans la clause' WHERE' et le 'SUBSELECT' ne dépend d'aucune colonne de la requête principale. – JHS

+0

La deuxième requête est meilleure ... –

Répondre

1

La seconde serait plus rapide et la raison en est le premier contient ce est appelé sous-requêtes corrélées. Les sous-requêtes ont une corrélation avec les enregistrements de la requête principale. Les sous-requêtes doivent donc être exécutées une fois pour chaque enregistrement correspondant dans la requête principale. Dans votre cas, il ne peut pas exécuter la sous-requête tant qu'elle n'a pas déterminé la valeur de verb_id dans la requête principale. C'est beaucoup de requêtes à exécuter.

Une EXPLAIN sur la première requête devrait indiquer ce problème. C'est généralement un drapeau rouge quand vous voyez cela dans un EXPLAIN.

1

Je pense que JOIN sera plus rapide car il est effectué une fois pour une requête, et aussi je voudrais essayer de filtrer verb_id dans JOIN

SELECT user_id, 
    verb_id, 
    COALESCE(p.photo_name, s.status) AS performedon 
FROM table1 
    JOIN table2 ON user_id = user_id -- joining the first column 
    JOIN table3 ON verb_id = verb_id -- joining the second column 
    LEFT JOIN photos p ON verb_id = 'photoliked' AND p.photo_id = column3 -- joining the column3 with specific table 
    LEFT JOIN statustable s ON verb_id = 'statusliked' AND s.status_id = column3 
1

Vous pouvez utiliser cette approche:

SELECT t.user_id, 
     t.verb_id, 
     p.photo_name AS performedon 
FROM table1 AS t 
    JOIN table2 AS t2 ON t2.user_id = t.user_id 
    JOIN table3 AS t3 ON t3.verb_id = t.verb_id 
    JOIN photos AS p ON p.photo_id = t.column3 
         AND t.verb_id = 'photoliked' 

UNION ALL 

SELECT t.user_id, 
     t.verb_id, 
     s.status 
FROM table1 AS t 
    JOIN table2 AS t2 ON t2.user_id = t.user_id 
    JOIN table3 AS t3 ON t3.verb_id = t.verb_id 
    JOIN statustable AS s ON s.status_id = t.column3 
          AND t.verb_id = 'statusliked' ;