mysql 的 子查询

最近在学子查询,发现有一个题目如下
要求查询出两门及两门以上不及格者的平均成绩
mysql 的 查询结果集
第一想法就是
先查询出 成绩 小于60 的所有人 再进行子查询

SELECT `name`,avg(score) FROM score WHERE `name` IN ( SELECT `name` FROM score WHERE score < 60 GROUP BY `name` HAVING  COUNT(name) >= 2 ) GROUP BY name

mysql 的 查询结果集
再想想,好像有点复杂了。

2.第二次,想能不能把不及格的成绩统计起来,再进行筛选

SELECT `name`,AVG(score)avg,SUM(IF(score<60,1,0)) c FROM score GROUP BY `name` HAVING c >= 2

mysql 的 查询结果集

看了答案跟我的第二种是一样的

SELECT `name`,AVG(score) avg,SUM(score<60) c FROM score GROUP BY `name` HAVING c >= 2

提问:有没有更简单 或者更复杂的sql提供参考。或者大佬们提供相关的sql子查询题讨论讨论,谢谢。

#############################分割线###################################

更新 2023-8-21 晚10点30分
学习到新的知识 关于FROM,EXISTS,SELF JOIN 子查询
1.FROM 型子查询,其中这么说,可以把查询出来的数据集当成一个临时表,把列看成变量

SELECT `name`,avg FROM
    ( SELECT `name`,AVG(score) avg,SUM(score<60) s FROM score GROUP BY `name` ) tmp
WHERE s >= 2

2.EXISTS 型 子查询 ,其实不太理解,为什么EXISTS里面的 可以用 * 来查所有数据

SELECT name,AVG( score ) FROM `score` s1
WHERE EXISTS
( SELECT * FROM score s2 WHERE s1.name = s2.name GROUP BY `name` HAVING SUM( score<60 ) >=2 ) GROUP BY `name`

2.SELF JOIN 自连接

SELECT s1.name,AVG(s1.score) FROM score s1
LEFT JOIN score s2 ON s1.`id` = s2.`id`
GROUP BY s1.`name`
HAVING SUM( s2.score < 60 ) >= 2

新表 user 数据如下 ,查询出数据用户,及用户上级用户信息(再关联其他表),按以前做法就是查询出所有数据再递归循环,现在一条sql就解决了。

mysql 的 子查询

SELECT u1.*,u2.name u2_name,u2.pid u2_pid FROM `user` u1
LEFT JOIN `user` u2 ON u1.id = u2.pid

查询过后的结果
mysql 的 子查询

本作品采用《CC 协议》,转载必须注明作者和本文链接
《L05 电商实战》
从零开发一个电商项目,功能包括电商后台、商品 & SKU 管理、购物车、订单管理、支付宝支付、微信支付、订单退款流程、优惠券等
《L01 基础入门》
我们将带你从零开发一个项目并部署到线上,本课程教授 Web 开发中专业、实用的技能,如 Git 工作流、Laravel Mix 前端工作流等。
讨论数量: 13

其实子查询,我工作这么多年了,几乎没用过,自己写SQL就是join,有用到也是ORM自带的。

1年前 评论
凌晨三点半的卢本伟 (楼主) 1年前

试试看, 行不行


SELECT `name`,avg(score) ,count(*) sum_score
FROM score 
WHERE `name` IN ( SELECT `name` FROM score WHERE score < 60 having count(*) > 1)
    and score < 60
GROUP BY name
1年前 评论
凌晨三点半的卢本伟 (楼主) 1年前
kis龍 (作者) 1年前
凌晨三点半的卢本伟 (楼主) 1年前

刚好几年前看过一本书叫 SQL 进阶教程, 里面有这样一段话:

很多人觉得 HAVING 子句像是影视剧里的配角 一样,并没有太多的出场机会,仿佛是一种附属品, 从而轻视了它 但是读过本节内容后, 相信大家就能明白, HAVING 子句其实是非常强大的, 它是面向集合语言的一大利器。 特别是与CASE 表达式或自连接等其他技术结合使用更能发挥它的威力。

但是这本书还有一段话更令我印象深刻:

我们在初学 SQL 的时候, 都学过对聚合结果进行条件判断时要用 HAVING 子句, 但从这道例题可以看到, 在 SELECT 语句里使用 CASE 表达式也可以完成同样的工作, 这种写法比较新颖。 如果用一句话来形容这个技巧, 可以这样说:

新手用 HAVING 子句进行条件分支, 高手用 SELECT 子句进行条件分支。

MICK. SQL进阶教程(图灵图书) (Kindle 位置 640-645). Kindle 版本.

我也不太会, 试着敲了一下, 貌似真行。

-- INSERT INTO test VALUES ('张三', '数学', 51);
-- INSERT INTO test VALUES ('张三', '语文', 59);
-- INSERT INTO test VALUES ('张三', '英语', 71);
-- 
-- INSERT INTO test VALUES ('李四', '数学', 62);
-- INSERT INTO test VALUES ('李四', '语文', 59);
-- INSERT INTO test VALUES ('李四', '英语', 71);
-- 
-- INSERT INTO test VALUES ('王五', '数学', 51);
-- INSERT INTO test VALUES ('王五', '语文', 53);
-- INSERT INTO test VALUES ('王五', '英语', 51);



SELECT
    `name`,
CASE

        WHEN COUNT(*) = 1 THEN 1
        WHEN COUNT(*) = 2 THEN 2
        ELSE 3
    END AS times 
FROM
    test 
WHERE score < 60
GROUP BY
    `name`;
name times
张三 2
李四 1
王五 3
1年前 评论
徵羽宫 (作者) 1年前
凌晨三点半的卢本伟 (楼主) 1年前
徵羽宫 (作者) 1年前
sanders
SELECT 
    AVG(`score`), `name`
FROM
    `score`
WHERE
    `name` IN (SELECT 
            `name`
        FROM
            (SELECT 
                *
            FROM
                `score`
            WHERE
                `score` < 60) filter_lt60
        GROUP BY `name`
        HAVING COUNT(`sub`) >= 2)
GROUP BY `name`;
1年前 评论
凌晨三点半的卢本伟 (楼主) 1年前
GDDD

file 这是gpt给的答案,没测试过

1年前 评论

讨论应以学习和精进为目的。请勿发布不友善或者负能量的内容,与人为善,比聪明更重要!