2011-07-03 28 views
5

Albo się starzeję, albo pytania, które muszę napisać, stają się coraz bardziej skomplikowane. Następująca kwerenda spowoduje, że cały tasks zostanie powiązany z użytkownikiem.scalanie dwóch zapytań SELECT

"SELECT `date` 
    FROM `tasks` 
    WHERE `user_id`= 1;" 

Tabela tasks oznacza (id, date, user_id, url_id);

Teraz muszę się dostać, a także zapisy, które url_id współpracownicy z użytkownikiem koryta

`urls` table (`id`, `user_id`) 

Zapytanie samodzielnym będzie wyglądać następująco:

"SELECT `t1`.`data` 
    FROM `tasks` `t1` 
    JOIN `urls` `u1` ON `u1`.`id` = `t1`.`url_id` 
    WHERE `u1`.user_id` = 1;" 

choć jest to możliwe do scalania te dwa zapytania do pojedynczego zapytania? Moja logika mówi, że tak powinno być, chociaż nie rozumiem, jak wykonać JOIN.

+0

Czy chodziło Ci o 'data' lub' date' w twoim ostatnim zapytaniu? Ponadto, jeśli nie wybierasz żadnych danych z tabeli adresów URL, czy naprawdę musisz do niego dołączyć? (Odpowiedź może brzmieć "tak, aby upewnić się, że istnieje wpis URL dla tego identyfikatora użytkownika".) I dlaczego tak wiele tyknięć wstecz; jest tak źle jak MS SQL Server i nawiasy kwadratowe! –

+0

Napisałem zapytanie po drodze, więc naturalnie zostawiłem kilka błędów. Masz jednak rację, musiała to być "date", a nie "data". Normalnie zignorowałbym uwagę na temat "back-ticks", chociaż masz dość wysoką reputację, więc jestem trochę ciekaw, dlaczego mówisz, że "jest tak źle, jak MS SQL Server i nawiasy kwadratowe"? Celem samych backticks jest zapewnienie, że serwer MySQL jest w stanie szybko zidentyfikować nazwy tabel i kolumn oraz aby uniknąć nieporozumień przy użyciu zastrzeżonych słów kluczowych, takich jak 'left' lub' right' w zestawach zagnieżdżonych. – Gajus

+0

To samo zastrzeżenie dotyczy nawiasów kwadratowych przez użytkowników MS SQL Server. Wygląda to na brzydkiego i jest całkowicie niestandardowe. Żadne inne DBMS nie obsługuje tyknięć wstecz ani nawiasów kwadratowych dla tego, co standard SQL nazywa "identyfikatory rozdzielone", które norma mówi, są ujęte w podwójne cudzysłowy; pojedyncze cudzysłowy są zarezerwowane dla ciągów. Różne systemy DBMS mają różne reguły dotyczące miejsca, w którym można używać słów kluczowych. Ta, której używam, pozwala w większości miejscach na słowa kluczowe jako identyfikatory. Najlepiej unikać cytatów, unikając słów kluczowych jako identyfikatorów. –

Odpowiedz

5

Prawdopodobnie użyłbym UNION.

SELECT `date` 
    FROM `tasks` WHERE `user_id`=1 
UNION 
SELECT `t1`.`date` 
    FROM `tasks` `t1` 
    INNER JOIN `urls` `u1` ON `u1`.`id` = `t1`.`url_id` 
    WHERE `u1`.user_id`=1; 
+0

Pamiętaj, że będziesz potrzebować 'UNION ALL', jeśli nie chcesz, aby usunięto duplikaty. – tvanfosson

+0

To dziwne. Nigdy wcześniej nie korzystałem z UNION-u i to już trzeci raz w ciągu ostatnich dwóch dni. :) Chociaż, dziękuję! – Gajus

+0

@Guy - nie ma za co, ale zastanawiam się, dlaczego nie udało się awansować? :-( – tvanfosson

1

Można to zrobić w jednym zapytaniu:

SELECT t.date 
    FROM TASKS t 
WHERE t.user_id = 1 
    OR EXISTS(SELECT NULL 
       FROM URLS u 
       WHERE u.id = t.url_id 
       AND u.user_id = 1) 

Jednak OR jest notorycznie złe wykonawca - to odpryski plan wykonania. Podział zapytania, łączenie zestawów wyników można wykonać za pomocą operatorów UNION lub UNION ALL. UNION usuwa duplikaty z ostatecznego zestawu wyników; UNION ALL nie usuwa duplikatów i działa szybciej.

SELECT t.date 
    FROM TASKS t 
WHERE t.user_id = 1 
UNION ALL 
SELECT t.date 
    FROM TASKS t 
WHERE EXISTS(SELECT NULL 
       FROM URLS u 
       WHERE u.id = t.url_id 
       AND u.user_id = 1) 

Znaj swoje dane, więc wiesz, które UNION operator najlepiej służy potrzeb.