设想一下这种场景,sql应该怎么写:学生表中保存了学生姓名和课程信息,现在需要把选修课程1和课程2的学生姓名打印出来。或者类似的,在订单表中,把既购买了商品A,也购买了商品B的订单号找出来。粗看起来,这样的需求用sql实现比较简单,在WHERE条件中把课程1和课程2的信息加进去即可,但仔细想想,好像又没那么容易,因为有的学生只选修了课程1(或者课程2),如果用IN这个关键字的话,又把这部分学生的信息查询出来了。
我们用个图来说明一下:
对于上面的数据,需要找出选修了课程id为1和2的学生姓名,显然,满足条件的只有Tom,那这样的sql怎样写呢?我们先把表创建起来,然后插入如上图所示的简单数据:
CREATE TABLE `t_student_course` (
`id` int(11) NOT NULL AUTO_INCREMENT COMMENT '主键',
`course_id` int(11) NOT NULL COMMENT '课程id',
`stu_name` varchar(32) NOT NULL COMMENT '学生姓名',
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
INSERT INTO `t_student_course` VALUES ('1', '1', 'Tom');
INSERT INTO `t_student_course` VALUES ('2', '2', 'Tom');
INSERT INTO `t_student_course` VALUES ('3', '1', 'John');
INSERT INTO `t_student_course` VALUES ('4', '3', 'John');
INSERT INTO `t_student_course` VALUES ('5', '1', 'Jerry');
正如上面所说的,如果我们直接在WHERE语句查询course_id等于1和2的数据,并且按照学生姓名分组,那返回的数据就有Tom、John和Jerry,显然是不对的。
SELECT stu_name FROM t_student_course WHERE course_id IN (1,2)
GROUP BY stu_name
我们需要在GROUP BY后面再加上过滤条件,也就是对分组后的数据记录条数是2,此时需要使用关键字HAVING,同时,在实际的数据表中,字段可能远远不这么几个,也可能会存在冗余的情况,所以需要过滤掉字段的重复值。最终的sql如下:
SELECT stu_name FROM t_student_course WHERE course_id IN (1,2)
GROUP BY stu_name
HAVING COUNT(DISTINCT course_id) = 2
执行的结果就是我们想要的答案:Tom.
都看到这里了,请帮忙一键三连啊,也就是点击文末的在看、点赞、分享,这样会让我的文章让更多人看到,也会大大地激励我进行更多的输出,谢谢!
推荐阅读:
原文始发于微信公众号(互联网全栈架构):一条sql搞定这个需求,面试官直呼内行
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/173645.html