【问题标题】:Retrieve rows from multiple entires for a given identifier and one column value from within a set of values only从给定标识符的多个条目中检索行,并仅从一组值中检索一个列值
【发布时间】:2018-08-27 12:52:31
【问题描述】:

我有一个用于存储审计的数据库表,如下所示(它只是实际表的简单表示,其中 STATUS 可以具有多个值之一)

身份证 |学生 ID |课程 ID |地位 1 | 5 | 12 |已注册 2 | 5 | 12 |进行中 3 | 2 | 12 |已注册 4 | 2 | 12 |完全的 5 | 5 | 12 |完全的 6 | 2 | 14 |已注册

我需要查找给定 STUDENT_ID 和 COURSE_ID 对的所有记录作为标识符,其中 STATUS 属于 Enrolled 和 Completed(即每个 Enrolled 和 Completed 状态有 2 条记录,或者 Enrolled 或 Completed 状态只有一条记录)。

注意 - 对于给定的 STUDENT_ID 和 COURSE_ID,不应存在 STATUS 不是 Enrolled & Completed 的条目。

输出表 -

身份证 |学生 ID |课程 ID |地位 3 | 2 | 12 |已注册 4 | 2 | 12 |完全的 6 | 2 | 14 |已注册

更新 - 如果我有另一个 STUDENT_ID 2 条目的状态为 In-Progress,它仍应返回状态为 Enrolled 和 Completed 的课程。

身份证 |学生 ID |课程 ID |地位 1 | 5 | 12 |已注册 2 | 5 | 12 |进行中 3 | 2 | 12 |已注册 4 | 2 | 12 |完全的 5 | 5 | 12 |完全的 6 | 2 | 14 |已注册 7 | 2 | 14 |进行中

输出表 -

身份证 |学生 ID |课程 ID |地位 3 | 2 | 12 |已注册 4 | 2 | 12 |完全的

【问题讨论】:

  • 我不明白你的输出学生 5 已经注册并完成了课程 12 那么为什么不输出学生 6 还没有完成课程 14?
  • @P.Salmon - 因为对于课程 12,学生 5 也有一个记录在进行中状态。对于任何学生课程对,都应仅具有已注册或已完成或既已注册又已完成状态。

标签: mysql sql select subquery relational-database


【解决方案1】:

在空测试中使用左连接

drop table if exists t;
create table t(ID int, STUDENT_ID int, COURSE_ID int, STATUS varchar(20));
insert into t values
(1  ,     5      , 12        , 'Enrolled'),
(2  ,     5      , 12        , 'In-Progress'),
(3  ,     2      , 12        , 'Enrolled'),
(4  ,     2      , 12        , 'Completed'),
(5  ,     5      , 12        , 'Completed'),
(6  ,     2      , 14        , 'Enrolled');


select t.* from t
left join
(select  student_id,course_id,count(*) from t where status not in('enrolled','completed') group by student_id,course_id) s
on t.STUDENT_ID = s.student_id and t.course_id = s.course_id 
where s.student_id is null;

+------+------------+-----------+-----------+
| ID   | STUDENT_ID | COURSE_ID | STATUS    |
+------+------------+-----------+-----------+
|    3 |          2 |        12 | Enrolled  |
|    4 |          2 |        12 | Completed |
|    6 |          2 |        14 | Enrolled  |
+------+------------+-----------+-----------+
3 rows in set (0.00 sec)

【讨论】:

    【解决方案2】:

    我只会排除 STUDENT_ID 和 COURSE_IDs 发现 In-Progress 状态:

    select t.*
    from table t
    where not exists (select 1 
                      from table t1 
                      where t1.student_id = t.student_id and 
                            t1.course_id = t.course_id and t1.status = 'In-Progress'
                     );
    

    【讨论】:

    • 正如我所提到的,STATUS 可以具有许多值之一,并且排除所有其他值对我来说并不理想。我不知何故必须在我的查询中只包含这两个值。
    【解决方案3】:

    正如您所提到的,您只需要这两个状态 - 'Enrolled','Completed' 您可以使用子查询实现您的目标

    SELECT t.* 
    FROM   students t 
    WHERE  student_id NOT IN (SELECT DISTINCT student_id 
                              FROM   students 
                              WHERE  status NOT IN ( 'Enrolled', 'Completed' ));
    

    【讨论】:

      【解决方案4】:

      使用 distinct 和 sub-query

       select distinct * from your_table 
          where STUDENT_ID not in 
            (  select STUDENT_ID from your_table 
               where STATUS in ('In-Progress')
            )
      

      http://sqlfiddle.com/#!9/f6d650/1

      ID  STUDENT_ID  COURSE_ID   STATUS
      3     2         12          Enrolled
      4     2         12          Completed
      6     2         14          Enrolled
      

      另一种方式

      select t1.* from
      (
      select * from yourtable 
      
      ) as t1
      
      left join  
      (
      select * from yourtable
                   where STATUS  in ('In-Progress')
      ) as t2 on t1.STUDENT_ID=t2.STUDENT_ID
      where t2.id is null
      

      http://sqlfiddle.com/#!9/f6d650/7

      ID  STUDENT_ID  COURSE_ID   STATUS
      3     2            12     Enrolled
      4     2            12     Completed
      6     2            14     Enrolled
      

      【讨论】:

        【解决方案5】:

        一种解决方案是返回一对 (STUDENT_ID, COURSE_ID),其中状态为 Enrolled 或 Completed,但不是其他任何内容:

        select
          student_id,
          course_id
        from
          students
        group by
          student_id,
          course_id
        having
          sum(status in ('Enrolled', 'Completed'))>0
          and sum(status not in ('Enrolled','Completed'))=0
        

        然后你可以用这个提取所有列:

        select *
        from students
        where
          (students_id, course_id) in (
            ..the select query above...
          )
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2018-05-26
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2020-08-22
          • 2012-01-27
          相关资源
          最近更新 更多