2016-02-28 51 views
2

我有这些表:SQL排除行,而不子查询

PERSON    COURSE    PERSON_COURSE 
+----+----------+ +----+----------+ +------+------+ 
| ID | Name  | | ID | Name  | | P_ID | C_ID |  
+----+----------+ +----+----------+ +------+------+ 
| P1 | Person 1 | | C1 | Course 1 | | P1 | C1 | 
| P2 | Person 2 | | C2 | Course 2 | | P1 | C2 | 
| P3 | Person 3 | | C3 | Course 3 | | P3 | C2 | 
+----+----------+ +----+----------+ | P3 | C3 | 
              +------+------+ 

,我想选择所有不参加课程C1人。

所以我使用的是:

select p.id 
from person p 
where p.id not in (
    select pc.p_id 
    from person_course pc 
    where pc.c_id != 'C1') 

现在,我想知道是否有可能获得相同的结果,而无需使用子查询。

回答

3

一个选项是左连接,试图与课程相匹配的人和我只包括没有匹配的人;

​​3210

An SQLfiddle to test with

1

我想选择所有不参加课程的人C1

你可以使用聚合:

SELECT P.ID, P.NAME 
FROM PERSON P 
LEFT JOIN PERSON_COURSE PC 
    ON P.ID = PC.P_ID 
GROUP BY P.ID, P.NAME 
HAVING SUM(CASE WHEN PC.C_ID = 'C1' THEN 1 ELSE 0 END) = 0; 

LiveDemo

输出:

╔════╦══════════╗ 
║ ID ║ Name ║ 
╠════╬══════════╣ 
║ P2 ║ Person 2 ║ 
║ P3 ║ Person 3 ║ 
╚════╩══════════╝ 
1

我只想指出,你可以使用子查询来做到这一点,但它不是问题中的问题。相反:

select p.id 
from person p 
where p.id not in (select pc.p_id 
        from person_course pc 
        where pc.c_id = 'C1' 
---------------------------------^ 
       ); 

(虽然我更喜欢NOT EXISTS这个逻辑,我保持这个类似于你的逻辑越好。)

小心双重否定。