【问题标题】:SQL exclude rows without subquerySQL 排除没有子查询的行
【发布时间】:2016-02-28 10:14:02
【问题描述】:

我有这些表:

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

现在,我想知道是否可以在不使用子查询的情况下获得相同的结果。

【问题讨论】:

    标签: sql subquery


    【解决方案1】:

    一个选项是左连接,尝试将人员与课程匹配,并且仅包括不匹配的人员;

    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;
    

    An SQLfiddle to test with.

    【讨论】:

      【解决方案2】:

      我想选择所有没有参加课程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 ║
      ╚════╩══════════╝
      

      【讨论】:

        【解决方案3】:

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

        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 这个逻辑,但我会尽可能地保持它与你的逻辑相似。)

        小心双重否定。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2021-06-12
          • 2016-03-20
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多