2011-12-08 13 views
24

Ok, więc mam jedną tabelę tymczasową, która zawiera identyfikator użytkownika i taskID. Nazywa się to CompletedTasks. Mam drugą tabelę, która zawiera ID użytkownika i taskID. Nazywa się PlannedTasks.mysql "Gdzie nie" przy użyciu dwóch kolumn

Potrzebuję uzyskać listę wszystkich ID zadań, które zostały zakończone, ale nie planowane. Tak więc, muszę jakoś wyeliminować z wykonanych zadań wszystkie wiersze, w których zarówno PlannedTasks.userID != CompletedTasks.userID AND PlannedTasks.taskID != CompletedTasks.taskID.

Mam nadzieję, że to pytanie ma sens. Daj mi znać, jeśli nie jest to jasne i wyjaśnię dalej.

Dzięki za wszelkie wskazówki!

+0

Myślę, że potrzebujesz dodatkowej kolumny do wskazania statusu, tak naprawdę nie potrzebujesz dwóch stołów. – ajreal

+0

@ajreal To jest dobra uwaga. Być może będę rozważał ulepszenie schematu w sposób, jaki zasugerowałeś. Doceń wskazówkę! – PFranchise

+1

Wolę 2 tabele od jednej tabeli i kolumnę statusu, 99% czasu. I 11 tabel na jeden stół i 10 kolumn statusu. Nie jest łatwo zoptymalizować zapytanie, które przeszukuje jedną lub wiele kolumn statusu (w MysQL). –

Odpowiedz

62

Można użyć tego (bardziej kompaktowy składnię):

SELECT * 
FROM CompletedTasks 
WHERE (userID, taskID) NOT IN 
     (SELECT userID, taskID 
     FROM PlannedTasks 
    ) ; 

lub wersję NOT EXISTS (które choć bardziej złożone, powinny być bardziej efektywne z odpowiednimi indeksami):

SELECT c.* 
FROM CompletedTasks AS c 
WHERE NOT EXISTS 
     (SELECT 1 
     FROM PlannedTasks AS p 
     WHERE p.userID = c.userID 
      AND p.taskID = c.taskID 
    ) ; 

i oczywiście wersja LEFT JOIN/IS NULL, którą @jmacinnes ma w swojej odpowiedzi.

+0

Awesome! Dziękuję Ci bardzo. Nie wiedziałem, że możesz użyć Gdzie na dwóch polach w ten sposób, ale miał nadzieję, że to będzie opcja. Jeszcze raz dziękuję i życzę udanego dnia! – PFranchise

+0

Po moich testach wersja NOT EXISTS jest szybsza niż wersja NOT_IN –

+0

@Ka. tak, "NOT IN" z krotką nie jest zoptymalizowane tak dobrze, jak "NOT EXISTS". Z którą wersją testowałeś? Nie testowałem, jeśli poprawiono optymalizator w nowej wersji 5.7. –

5

Czy tego właśnie potrzebujesz?

select ct.* from 
completedTasks ct 
left outer join plannedTasks pt on ct.taskId = pt.TaskId and ct.userId = pt.userId 
where pt.taskId is null 

Jednak zgadzam się z komentarzem - biorąc pod uwagę to, co wiemy od kwestii kolumna stan brzmi jak lepszego schematu niż dwóch tabel.

0

@ ypercubeᵀᴹ Dziękujemy za dzielenie poniżej zapytania wzmianka

SELECT * FROM CompletedTasks WHERE (userID, taskID) NOT IN 
     (SELECT userID, taskID FROM PlannedTasks) ;' 

Mój problem rozwiązany.

+0

To powinien być komentarz, a nie odpowiedź :) – sniperd

+0

Właściwie wprowadziłem pewne zmiany w odniesieniu do współdzielonej kwerendy @ypercube. Zaopiekuje się w przyszłości. Dzięki –

Powiązane problemy