zoukankan      html  css  js  c++  java
  • SQL 强化练习 (七)

    继续 sql 练习, 不能停下来的哦, 通过这一系列的搬砖操作, 相信在日常业务的sql 应该是能达到相对清楚地写出来的, 尤其是我做数据分析这块, 感觉真的每天都要写才行, 之前都是用 Python 来轻松搞定, 但仔细一想, sql 才是最通用的哦, sql 熟练了, 我感觉, 数据分析的基础工作就已经完成一半了, 剩下的指标计算, 这些不就是简单的 加减乘除而已, 分分钟脚本批量处理它.

    表关系

    需求

    查询 和 0001 号同学, 所学课程 完全相同的 其他同学的学号.

    分析

    1. 先查出 0001 这个兄弟, 的所有课程 id;

    2. 然后查出 not in 这些 课程 id 的这些 学号;

    3. 还要完全相同, 则, group by s_id 后, 选课的数量还必须一致哦.

    4. 从 3 中 排除掉 2 中的 id 剩下的就是满足条件的啦

    -- 1. 先看看 0001 这个兄弟选了哪些课程
    select c_id from score where s_id = '0001'; 
    
    +------+
    | c_id |
    +------+
    | 0001 |
    | 0002 |
    | 0003 |
    +------+
    3 rows in set (0.01 sec)
    
    

    都给选上了. 即下一步, 要找的学生, 必须都同时选了 1,2,3号课程, 注意不能多哦 , 要完全相同.

    -- 2. 反向来看, 没有跟 0001 兄弟选课一样的那些人是谁
    
    select s_id 
    
    from score 
    where c_id not in (
      select c_id from score where s_id = '0001'
    ); 
    

    Empty set (0.00 sec)

    空的哦, 还行的.

    -- 4. 把那些选课数量 跟 0001 相同的 兄弟给找出来. 
    select 
      s_id 
    from score 
    where s_id != "0001"
    group by s_id having
      -- 数量一致的兄弟
      count(distinct c_id) = (select count(distinct c_id) from score 
      where s_id = "0001")
    
    
    +------+
    | s_id |
    +------+
    | 0003 |
    +------+
    1 row in set (0.00 sec)
    

    最后是,从选课数量相同的那些学号中, 过滤掉, 没有选课一样的 那些 id , 剩下的就是呀.

    select
      s_id as "学号", 
      s_name as "姓名"
    from student where s_id in (
    
      select 
        s_id 
      from score 
      where s_id != "0001"
      group by s_id having
        count(distinct c_id) = (select count(distinct c_id) from score 
        where s_id = "0001")
      )
    
    and s_id not in (
    
    select s_id 
    
    from score 
    where c_id not in (
      select c_id from score where s_id = '0001'
      )
    );
    
    +--------+-----------+
    | 学号   | 姓名      |
    +--------+-----------+
    | 0003   | 胡小适    |
    +--------+-----------+
    1 row in set (0.01 sec)
    

    感觉写起来有点绕, 不过逻辑还是蛮清楚的哦. 感觉还是要重新来复盘一波的.

    首先呢, step 1 可以轻易查到, 0001 这个兄弟 选了 1,2,3 门课程.

    于是 step2 先选出, 所学课 不在 (not in) (1,2,3) 的同学的学号, 这些事必须要排除的哦.

    在来 step3 基于 step2 所剩下的同学, 必然是选了 1, 2,3 中的 某几门 课程, 究竟选了几门, 则判断其课程总数 跟 001 这个兄弟的课程数是相等的 学号即可.

    关键就是这个 in 和 not in 的用法, 这个题的逻辑还是, 有点东西的我感觉.

    小结

    • 总体问题进行拆解, 分块查询出结果, 跟咱写代码框架是一样的哦.
    • 应用反向思维, in 和 not in 的配合使用
    • 子查询, 查询集的逻辑理清楚, 小 tips 就是 取别名和加括号来区分, 同时注意排版哦.
  • 相关阅读:
    整合SSH遇到的问题
    学习动态代理实现业务层的事务控制遇到的问题
    docker局域网独立IP外网访问配置
    第23次CSP-D题解法
    Nordic Bluetooth 切换到DFU Mode
    MySQL事务、锁和MVCC
    深拷贝和浅拷贝的区别是什么?
    python是如何进行内存管理的
    数据库的事务
    斐波那契数列
  • 原文地址:https://www.cnblogs.com/chenjieyouge/p/12638699.html
Copyright © 2011-2022 走看看