SQL 排除没有子查询的行
SQL exclude rows without subquery
我有这些表:
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 |
+------+------+
我想select 所有没有参加课程 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')
现在,我想知道是否可以在不使用子查询的情况下获得相同的结果。
I want to select all persons which does not attend course 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;
输出:
╔════╦══════════╗
║ ID ║ Name ║
╠════╬══════════╣
║ P2 ║ Person 2 ║
║ P3 ║ Person 3 ║
╚════╩══════════╝
一个选项是左连接,试图将人员与课程相匹配,并且只包括没有匹配的人员;
SELECT p.*
FROM person p
LEFT JOIN person_course pc
ON p.id = pc.p_id
AND pc.c_id = 'C1'
WHERE pc.c_id IS NULL;
我只想指出,您可以使用子查询来执行此操作,但它不是问题中的那个。相反:
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
这个逻辑,但我会尽可能地保持它与你的逻辑相似。)
注意双重否定。
我有这些表:
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 |
+------+------+
我想select 所有没有参加课程 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')
现在,我想知道是否可以在不使用子查询的情况下获得相同的结果。
I want to select all persons which does not attend course 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;
输出:
╔════╦══════════╗
║ ID ║ Name ║
╠════╬══════════╣
║ P2 ║ Person 2 ║
║ P3 ║ Person 3 ║
╚════╩══════════╝
一个选项是左连接,试图将人员与课程相匹配,并且只包括没有匹配的人员;
SELECT p.*
FROM person p
LEFT JOIN person_course pc
ON p.id = pc.p_id
AND pc.c_id = 'C1'
WHERE pc.c_id IS NULL;
我只想指出,您可以使用子查询来执行此操作,但它不是问题中的那个。相反:
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
这个逻辑,但我会尽可能地保持它与你的逻辑相似。)
注意双重否定。