2012-06-20 26 views
6

Mam tabelę powiedzieć table1, który ma 3 kolumny column1, column2 and column3.LEFT OUTER JOIN vs SUBSELECT w MySQL

The column1 i column2FOREIGN KEY z 2 innymi tabelami. Jednak dane w column3 pochodzą z liczby n tabel.

Dla np. Rozważmy Facebooka. Aby wyświetlić działania, może on utrzymywać tabelę, która może mieć wartość user1 photoliked photo1 lub. W takim przypadku column3 nie może być FOREIGN KEY z określoną tabelą.

Teraz są 2 sposoby na uzyskanie prawdziwego danych -

1-ty sposób -

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 sposób -

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 

Pytanie

Które z 2 sposoby lepiej jest odzyskać dane? i które z 2 zapytań jest tańsze?

+0

Możliwy duplikat http://stackoverflow.com/a/10684539/1239506 –

+0

Nie, to nie jest duplikat. W pytaniu tym występuje "IN" w klauzuli "WHERE", a "SUBSELECT" nie zależy od żadnej kolumny głównej zapytania. – JHS

+0

Druga kwerenda jest lepsza ... –

Odpowiedz

1

drugim byłoby szybciej, a powodem jest to pierwsza zawiera co nazywa się skorelowane podzapytania. Podzapytania mają korelację z rekordami z kwerendy głównej. Tak więc podzapytania należy uruchomić raz dla każdego pasującego rekordu w zapytaniu głównym. W twoim przypadku nie może uruchomić podzapytania, dopóki nie określi wartości verb_id w zapytaniu głównym. To dużo pytań do uruchomienia.

EXPLALNE w pierwszym zapytaniu powinny wskazywać ten problem. Zazwyczaj jest to czerwona flaga, gdy widzisz to w EXPLAIN.

1

myślę JOIN będzie szybsze, gdyż odbywa się raz na zapytania, a także chciałbym spróbować filtrować verb_id w 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

Można użyć tej metody:

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' ;