Bootstrap

SQL39道常见题型

SQL1 查询所有列

现在运营想要查看用户信息表中所有的数据,请你取出相应结果。

select * from user_profile

结果:

SQL2 查询多列

还是上面那个输入,题目换成:现在运营同学想要用户的设备id对应的性别、年龄和学校的数据,请你取出相应数据。

select device_id, gender,age,university from user_profile

选择指定的列: SELECT 字段名 FROM 表名;

SQL3 查询结果去重

现在运营需要查看用户来自于哪些学校,请从用户信息表中取出学校的去重数据。

两种方式:

1.distinct 关键字

select DISTINCT university FROM user_profile;

select distinct university from user_profiledistinct去重,放在列的前面使用。

2.分组group by 来筛选出去重的结果

当你对某个列使用 GROUP BY 时,数据库会将该列中相同值的行分为一组。对于每一组,只返回一个记录。因此,在对特定列进行 GROUP BY 操作时,相当于对该列进行去重。

select university FROM user_profile group by university;

SQL4 查询结果限制返回行数

现在运营只需要查看前2个用户明细设备ID数据,请你从用户信息表 user_profile 中取出相应结果。

select device_id from  user_profile LIMIT 2;

其他用法:

取按特定顺序排序的前几条记录

SELECT * FROM user_profile ORDER BY registration_date DESC LIMIT 2;

选择中间的任意几行

SELECT * FROM table LIMIT count OFFSET offset;
  • count:要返回的行数。
  • offset:要跳过的行数。
SELECT * FROM table LIMIT 3 OFFSET 2;
  • OFFSET 2:跳过前2行。
  • LIMIT 3:返回接下来的3行。

.检索记录行 6-10

SELECT * FROM table LIMIT 5,5

检索记录行 11-last

SELECT * FROM table LIMIT 10,-1

SQL5 将查询后的列重新命名

SELECT device_id AS user_infos_example FROM user_profile LIMIT 2;

AS可以省略

SELECT device_id user_infos_example FROM user_profile LIMIT 2;

SQL6 查找学校是北大的学生信息

现在运营想要筛选出所有北京大学的学生进行用户调研,请你从用户信息表中取出满足条件的数据,结果返回设备id和学校。

select device_id,university from user_profile where university='北京大学';
select device_id,university from user_profile where university like '%北京%'

'%北京%' 的意思是匹配所有包含“北京”这个子字符串的字符串,不论它出现在字符串的开头、中间还是结尾。它使用 SQL 中的 LIKE 子句来查找包含特定子字符串的行。

SQL7 查找年龄大于24岁的用户信息

现在运营想要针对24岁以上的用户开展分析,请你取出满足条件的设备ID、性别、年龄、学校。

select device_id,gender,age,university from user_profile where age>24;

严谨起见,可以加上 age is not null 的条件

select device_id,gender,age,university from user_profile where age is not null and age>24;

SQL8 查找某个年龄段的用户信息

现在运营想要针对20岁及以上且23岁及以下的用户开展分析,请你取出满足条件的设备ID、性别、年龄.
1.between 在列值得某与某之间

select device_id,gender,age from user_profile where age between 20 and 23;

2.用and的来连接条件范围

select device_id,gender,age from user_profile where age >=20 and age <=23;

SQL9 查找除复旦大学的用户信息

现在运营想要查看除复旦大学以外的所有用户明细,请你取出相应数据.

select device_id,gender,age,university from user_profile where university <> '复旦大学';
select device_id,gender,age,university from user_profile where university != '复旦大学';

如果你想对查询结果进行去重,确保每个学校和id等信息只出现一次,可以使用 DISTINCT 关键字来实现。DISTINCT 用于返回不同的唯一值。

select DISTINCT device_id,gender,age,university from user_profile where university != '复旦大学';

SQL10 用where过滤空值练习

现在运营想要对用户的年龄分布开展分析,在分析时想要剔除没有获取到年龄的用户,请你取出所有年龄值不为空的用户的设备ID,性别,年龄,学校的信息。

select device_id,gender,age,university from user_profile where age is not null;
select device_id,gender,age,university from user_profile where age is not null and age <> "";

 返回所有 age 列值既不为空(NULL)也不等于空字符串 "" 的记录。

select device_id,gender,age,university from user_profile where age is not null and age <> 0;

SQL11 高级操作符练习(1) -AND 

现在运营想要找到男性且GPA在3.5以上(不包括3.5)的用户进行调研。

select device_id,gender,age,university,gpa from user_profile where gpa >3.5 and gender = "male";

IN 操作符用于匹配多个可能的值,在这里只匹配 'male',所以 gender = 'male'gender IN ('male') 是等效的。 

select device_id,gender,age,university,gpa from user_profile where gpa >3.5 and gender in('male');

SQL12 高级操作符练习(2)-OR

现在运营想要找到学校为北大或GPA在3.7以上(不包括3.7)的用户进行调研,请你取出相关数据(使用OR实现)

select device_id,gender,age,university, gpa from user_profile where gpa>3.7 OR university IN('北京大学')
select device_id,gender,age,university, gpa from user_profile where gpa>3.7 OR university ='北京大学';

SQL13 Where in 和Not in

现在运营想要找到学校为北大、复旦和山大的同学进行调研,请你取出相关数据。

select device_id,gender,age,university,gpa from user_profile where university in ('北京大学','复旦大学','山东大学');
select device_id,gender,age,university,gpa from user_profile where university='北京大学' or university='复旦大学' or university='山东大学';

SQL14 操作符混合运用

现在运营想要找到gpa在3.5以上(不包括3.5)的山东大学用户 或 gpa在3.8以上(不包括3.8)的复旦大学同学进行用户调研,请你取出相应数据。

select device_id,gender,age,university,gpa from user_profile where gpa>3.5 and university='山东大学' or gpa >3.8 and university='复旦大学';

AND 的优先级高于 OR。这意味着在没有括号的情况下,AND 运算会比 OR 运算先被计算。

SELECT device_id, gender, age, university, gpa
FROM user_profile
WHERE (gpa > 3.5 AND university = '山东大学')
   OR (gpa > 3.8 AND university = '复旦大学');

SQL15 查看学校名称中含北京的用户

现在运营想查看所有大学中带有北京的用户的信息,请你取出相应数据。

select device_id,age,university from user_profile where university lIKE('%北京%');

LIKE 的用法

  1. 百分号 (%):

    • 用法:用于匹配零个或多个字符。
    • 示例
      • LIKE 'A%' 匹配以 'A' 开头的所有记录。
      • LIKE '%A' 匹配以 'A' 结尾的所有记录。
      • LIKE '%A%' 匹配包含 'A' 的所有记录。
      • LIKE 'A%B' 匹配以 'A' 开头,'B' 结尾的记录,中间可以有零个或多个字符。
  2. 下划线 (_):

    • 用法:用于匹配一个单独的字符。
    • 示例
      • LIKE 'A_' 匹配以 'A' 开头,后跟一个字符的记录。
      • LIKE '_A' 匹配以一个字符开头,后跟 'A' 的记录。
      • LIKE '_A_' 匹配一个字符,后跟 'A' 和一个字符的记录。
  3. 转义字符:

    • 用法:用于在模式中匹配实际的百分号 (%) 或下划线 (_) 字符。这些字符通常被视为通配符,但可以使用转义字符来匹配它们。
    • 示例
      • LIKE '100\%' ESCAPE '\' 匹配 '100%' 字符串,其中 \ 是转义字符。
      • LIKE 'A\_B' ESCAPE '\' 匹配 'A_B' 字符串,其中 \ 用来转义下划线。

SQL16 查找GPA最高值

运营想要知道复旦大学学生gpa最高值是多少,请你取出相应数据。

因最高的gpa,max(gpa)求出最大值

select max(gpa) as gpa from user_profile where university='复旦大学';

因最高的gpa,进行order by gpa desc降序,取第一行的数据即可 

select gpa from user_profile where university='复旦大学' order by gpa desc limit 1;

SQL17 计算男生人数以及平均GPA

现在运营想要看一下男性用户有多少人以及他们的平均gpa是多少,用以辅助设计相关活动

select count(gender) as male_num, avg(gpa) as avg_gpa from user_profile where gender='male';

严谨到小数点, ROUND函数

ROUND(numeric_expression, decimal_places)

  • numeric_expression:要四舍五入的数值表达式。
  • decimal_places:要保留的小数位数。如果省略此参数,默认将四舍五入到最接近的整数。
select count(gender) as male_num,ROUND(avg(gpa),1) as avg_gpa from user_profile where gender='male';

SQL18 分组计算练习题

现在运营想要对每个学校不同性别的用户活跃情况和发帖数量进行分析,请分别计算出每个学校每种性别的用户数、30天内平均活跃天数和平均发帖数量。

select gender,university,count(device_id) as user_num , avg(active_days_within_30) as avg_active_day ,avg(question_cnt) as avg_question_cnt from user_profile group by university,gender;
  • 每个学校每种性别:按学校和性别分组:group by gender, university
  • 用户数:count(device_id)
  • 30天内平均活跃天数:avg(active_days_within_30)
  • 平均发帖数量:avg(question_cnt)
  • 表头重命名:as

SQL19 分组过滤练习题

现在运营想查看每个学校用户的平均发贴和回帖情况,寻找低活跃度学校进行重点运营,请取出平均发贴数低于5的学校或平均回帖数小于20的学校。

  • 限定条件:平均发贴数低于5或平均回帖数小于20的学校,avg(question_cnt)<5 or avg(answer_cnt)<20,聚合函数结果作为筛选条件时,不能用where,而是用having语法,配合重命名即可;
  • 按学校输出:需要对每个学校统计其平均发贴数和平均回帖数,因此group by university
select university, ROUND(AVG(question_cnt),3) AS avg_question_cnt,ROUND(AVG(answer_cnt),3) AS avg_answer_cnt FROM user_profile group by university having avg_question_cnt <5 or avg_answer_cnt<20;
  • 表头重命名:as
  • 用having不用where

不考虑小数点;

select
    university,
    avg(question_cnt) as avg_question_cnt,
    avg(answer_cnt) as avg_answer_cnt
from user_profile
group by university
having avg_question_cnt<5 or avg_answer_cnt<20

SQL20 分组排序练习题

现在运营想要查看不同大学的用户平均发帖情况,并期望结果按照平均发帖情况进行升序排列,请你取出相应数据。

  • 不同大学:按学校分组group by university
  • 平均发帖数:avg(question_cnt)
  • 升序排序:order by avg_question_cnt
  • 表头重命名:as
select university, avg(question_cnt) as avg_question_cnt from user_profile group by university order by avg_question_cnt;

 HAVING 子句用于在分组后过滤结果,而 ORDER BY 子句用于对最终结果进行排序。如果有过滤条件的话加上having

select university, avg(question_cnt) as avg_question_cnt from user_profile group by university having avg_question_cnt is not null order by avg_question_cnt;

例如只选择平均发帖数量大于一定值的学校

SELECT university, AVG(question_cnt) AS avg_question_cnt
FROM user_profile
GROUP BY university
HAVING AVG(question_cnt) > 10
ORDER BY avg_question_cnt;

SQL21 浙江大学用户题目回答情况

现在运营想要查看所有来自浙江大学的用户题目回答明细情况。

 

 解法一:

select qpd.device_id,qpd.question_id,qpd.result from question_practice_detail as qpd inner join user_profile as up on qpd.device_id=up.device_id where university='浙江大学';

来自浙江大学的用户,学校信息在user_profile表中,答题明细在question_practice_detail表中,故需要使用device_id把两个表连接起来,方法1:join两个表,用inner join,条件是on up.device_id=qpd.device_id and up.university='浙江大学'

ON 子句:在连接操作中指定两个表之间的匹配条件。

连接类型:不同的连接类型(INNER, LEFT, RIGHT, FULL)决定了结果集中包含哪些行。

 解法二:子查询来实现,这个子查询首先筛选出符合条件的 device_id,然后在主查询中使用这些 device_id 来过滤数据。

select device_id,question_id,result from question_practice_detail where device_id in (select device_id from user_profile where university='浙江大学');

子查询从 user_profile 表中筛选出所有 university 为 '浙江大学' 的 device_id

主查询从 question_practice_detail 表中选择 device_idquestion_idresult,其中 device_id 在子查询返回的列表中。

SQL22 统计每个学校的答过题的用户的平均答题数

运营想要了解每个学校答过题的用户平均答题数量情况,请你取出数据。

select
    university,
    count(question_id) / count(distinct qpd.device_id) as avg_answer_cnt
from
    question_practice_detail as qpd
    inner join user_profile as up on qpd.device_id = up.device_id
group by
    university;
select
    up.university,
    count(qpd.question_id) / count(distinct qpd.device_id) as avg_answer_cnt
from
    question_practice_detail as qpd
    inner join user_profile as up on qpd.device_id = up.device_id
group by
    up.university;
select
    up.university,
    count(qpd.question_id) / count(distinct qpd.device_id) as avg_answer_cnt
from
    user_profile as up
    inner join question_practice_detail as qpd on qpd.device_id = up.device_id
group by
    up.university;

SQL23 统计每个学校各难度的用户平均刷题数

运营想要计算一些参加了答题的不同学校、不同难度的用户平均答题量

select up.university, qp.difficult_level,count(qpd.question_id)/count(distinct qpd.device_id) as avg_answer_cnt from question_practice_detail as qpd 
left join question_detail as qp
on qp.question_id= qpd.question_id
left join user_profile as up
on up.device_id=qpd.device_id
group by up.university,qp.difficult_level;
  • 每个学校:按学校分组group by university
  • 不同难度:按难度分组group by difficult_level
  • 平均答题数:总答题数除以总人数count(qpd.question_id) / count(distinct qpd.device_id)
  • 来自上面信息三个表,需要联表,up与qpd用device_id连接,qd与qpd用question_id连接。

SQL24 统计每个用户的平均刷题数

 运营想要查看参加了答题的山东大学的用户在不同难度下的平均答题题目数,

  • 链接三个表后,以学校和难度分组
  • 分组完成后用having 过滤
select up.university,qd.difficult_level,count(qpd.question_id)/count(distinct qpd.device_id) as avg_answer_cnt from question_practice_detail as qpd 
left join question_detail as qd
on qd.question_id=qpd.question_id
left join user_profile as up
on up.device_id	=qpd.device_id	
group by up.university,qd.difficult_level
having up.university='山东大学';
select up.university,qd.difficult_level,count(qpd.question_id)/count(distinct qpd.device_id) as avg_answer_cnt
from 
    user_profile as up,
    question_practice_detail as qpd,
    question_detail as qd
where 
    up.university='山东大学' 
    and qpd.device_id=up.device_id 
    and qpd.question_id=qd.question_id
group by qd.difficult_level;

SQL25 查找山东大学或者性别为男生的信息

现在运营想要分别查看学校为山东大学或者性别为男性的用户的device_id、gender、age和gpa数据,请取出相应结果,结果不去重。

注意:用where和or就是查询学校是山东大学或者为男生的信息。where和or一起用有去重作用,和union的作用一样。所以以下语句是错误的:

select device_id,gender,age,gpa from user_profile 
where university='山东大学' or gender='male';
  • 限定条件:学校为山东大学或者性别为男性的用户:university='山东大学'gender='male'
  • 分别查看&结果不去重:所以直接使用两个条件的or是不行的,直接用union也不行,要用union all,分别去查满足条件1的和满足条件2的,然后合在一起不去重。
select device_id,gender,age,gpa from user_profile 
where university='山东大学' 
union all
select device_id,gender,age,gpa from user_profile 
where gender='male';

SQL26 计算25岁以上和以下的用户数量

现在运营想要将用户划分为25岁以下和25岁及以上两个年龄段,分别查看这两个年龄段用户数量

本题注意:age为null 也记为 25岁以下。

CASE 表达式在 SQL 中用于进行条件判断,并返回相应的结果。它有两种形式:简单 CASE 和搜索 CASE

简单 CASE 表达式

简单 CASE 表达式用于比较一个表达式与一组简单的值,并根据匹配的结果返回相应的值。

CASE expression
    WHEN value1 THEN result1
    WHEN value2 THEN result2
    ...
    ELSE resultN
END

搜索 CASE 表达式

搜索 CASE 表达式用于基于布尔条件进行判断,并返回相应的结果。

CASE
    WHEN condition1 THEN result1
    WHEN condition2 THEN result2
    ...
    ELSE resultN
END

这个题就是搜索 CASE 表达式

select case 
    when age<25 or age is null then '25岁以下' 
    when  age>=25 then '25岁及以上' end age_cut,count(*)number 
    from user_profile group by age_cut

as 可以省略,不省略如下:

select case 
    when age<25 or age is null then '25岁以下' 
    when  age>=25 then '25岁及以上' end as age_cut,count(*) as number 
    from user_profile group by age_cut

SQL27 查看不同年龄段的用户明细

现在运营想要将用户划分为20岁以下,20-24岁,25岁及以上三个年龄段,分别查看不同年龄段用户的明细情况,请取出相应数据。(注:若年龄为空请返回其他。)

  • 划分年龄段:数值条件判断,可以用多重if,不过更方便的是用case when [expr] then [result1]...else [default] end
select device_id,gender, 
case when age<20 then '20岁以下' 
     when age>=20 and age<=24 then '20-24岁'
     when age >=25 then '25岁及以上'
     else '其他'
     end age_cut 
from user_profile

SQL28 计算用户8月每天的练题数量

现在运营想要计算出2021年8月每天用户练习题目的数量.

  • 2021年8月,写法有很多种,比如用year/month函数的year(date)=2021 and month(date)=8,比如用date_format函数的date_format(date, "%Y-%m")="202108"
  • 每天:按天分组group by date
  • 题目数量:count(question_id)
  • 表头重命名:as
  • 输出示例中每天的字段只取了几号,要去掉年月,用day函数即可
  • DAY(date) AS day 提取了每个 order_date 中的“日”部分,并将其列名命名为 day
select day(date) as day,count(question_id) as question_cnt
from question_practice_detail where month(date)=8 and year(date)=2021
group by date;

SQL29 计算用户的平均次日留存率

现在运营想要查看用户在某天刷题后第二天还会再来刷题的平均概率.

SQL30 统计每种性别的人数--字符串

现在运营举办了一场比赛,收到了一些参赛申请,表数据记录形式如下所示,现在运营想要统计每个性别的用户分别有多少参赛者,

-- 提取 profile 列中最后一个逗号分隔的部分作为性别

-- 计算每种性别的用户数量

-- 按性别分组

第一种解法SUBSTRING_INDEX

select substring_index(profile,",",-1) as gender ,count(*) as number from user_submit group by gender;

substring_index(str,delim,count)

str:要处理的字符串

delim:分隔符

count:技术

例子:str=www.wikibt.com

substring_index(str,'.',1) 结果是www

substring_index(str,'.',2)  结果是www.wikibt

substring_index(str,'.',-2)  结果是wikibt.com

也就是说:如果count是正数,就是从左往右数到第count个分隔符,然后取到分隔符左边的所有字符,如果count是负数,例如-2,就是从右往左数,数到第二个分隔符,取到右边的所有字符。

如果我需要取到中间的字符例如wikibt: substring_index(substring_index(str,'.',-2) ,'.',1)

第二种解法when .... then....end ...

select case 
when profile like'%,male' then 'male' 
when profile like'%,female' then 'female'
end as gender,count(device_id) as number
from user_submit group by gender

这种适合要去的字符串在整个字符串的结尾。

LIKE 运算符的使用:

  • LIKE '%,male'LIKE '%,female' 用于匹配以 ,male,female 结尾的 profile 字符串。

第三种解法IF 函数

IF 函数来根据 profile 列的值确定性别,并统计每种性别的用户数量。

COUNT(*) AS number:计算每个性别组的所有记录数,包括 profile 列中值为 NULL 的记录(如果有的话)。

select
    if (profile like '%female', 'female', 'male') as gender,
    count(device_id) as number
from
    user_submit
group by
    gender;

IF(profile LIKE '%female', 'female', 'male'):

  • 该函数会检查 profile 列的每个值。如果 profilefemale 结尾,则 gender 列的值为 'female';否则为 'male'
  • '%female' 的意思是查找任何以 "female" 结尾的字符串。

COUNT(device_id) AS number:计算每个性别组中 device_id 列非 NULL 值的记录数。如果 device_id 列中有 NULL 值,这些记录不会被计入总数。 

select
    if (profile like '%female', 'female', 'male') as gender,
    count(*) as number
from
    user_submit
group by
    gender;

SQL31 提取博客URL中的用户名

对于申请参与比赛的用户,blog_url字段中url字符后的字符串为用户个人博客的用户名,现在运营想要把用户的个人博客用户字段提取出单独记录为一个新的字段,请取出所需数据。

 第一种方法substring_index

select device_id ,
substring_index(blog_url,'/',-1) as user_name 
from user_submit;

第二种方法 REPLACE函数

  • REPLACE(blog_url, 'http:/url/', '')
    • REPLACE 是一个字符串函数,用于将字符串中的某个部分替换为另一个字符串。
    • 第一个参数 blog_url:这是待处理的列。
    • 第二个参数 'http:/url/':这是要被替换的子字符串。
    • 第三个参数 '':这是替换后的新字符串,这里是一个空字符串,意味着删除匹配的子字符串。
select device_id ,
replace(blog_url,'http:/url/','') as user_name 
from user_submit;

第三种方法删除法 trim 函数

TRIM([[LEADING | TRAILING | BOTH] [remstr] FROM] str)
  • LEADING:删除字符串 str 开头的 remstr 字符串。
  • TRAILING:删除字符串 str 结尾的 remstr 字符串。
  • BOTH(默认):删除字符串 str 开头和结尾的 remstr 字符串。
  • remstr:要删除的字符或字符串。
  • str:待处理的字符串。

 删除开头的子字符串

select device_id ,
TRIM(LEADING 'http:/url/' FROM blog_url) as user_name 
from user_submit;

 删除首尾的子字符串

select device_id ,
TRIM('http:/url/' FROM blog_url) as user_name
from user_submit;

第四种方法SUBSTR 函数或 SUBSTRING 函数

select device_id ,
substr(blog_url,11,length(blog_url)-10) as user_name
from user_submit;

SUBSTR(blog_url, 11, LENGTH(blog_url) - 10)

  • blog_url 是要处理的字符串列。
  • 11 是起始位置,从字符串的第 11 个字符开始(字符串索引从 1 开始)。
  • LENGTH(blog_url) - 10 提取长度为字符串总长度减去 10。有助于忽略 blog_url 列中的前 10 个字符,提取其余部分。

 SQL32 截取出年龄

现在运营举办了一场比赛,收到了一些参赛申请,表数据记录形式如下所示,现在运营想要统计每个年龄的用户分别有多少参赛者,请取出相应结果

select substring_index(substring_index(profile,',',-2),',',1) as age,
count(*) as number 
from user_submit group by age;

SQL33 找出每个学校GPA最低的同学

现在运营想要找到每个学校gpa最低的同学来做调研,请你取出每个学校的最低gpa。一个学校有多个学生。

SELECT 
    device_id,
    university,
    MIN(gpa) AS gpa
FROM 
    user_profile
GROUP BY 
    university
ORDER BY 
    university;

 这种方法会导致出错,因为查询中的 device_id 列与聚合函数 MIN(gpa) 之间存在不一致性。

在这种查询中,device_id 是一个非聚合列,而对 gpa 使用了聚合函数 MIN(gpa)。SQL 无法确定在同一组内 device_id 应该如何处理,因为 device_id 在每个组中可能有多个不同的值。

选择的列与 GROUP BY 不一致

  • GROUP BY university 将数据按学校分组。
  • MIN(gpa) AS gpa 会计算每个学校的最低 GPA。
  • device_id 列没有被 GROUP BY 处理或聚合,因此 SQL 不知道如何将 device_id 和最低 GPA 对应起来。也就是说根据学校分组之后,每组里面只有一个最小gpa,但是有多个device_id,不知道对于每个学校的最低 GPA 应该选择哪一个 device_id。

正确的方法

第一种子查询 

SELECT
    a.device_id,
    a.university,
    a.gpa
FROM
    user_profile as a
WHERE
    a.gpa in (
        SELECT
            MIN(b.gpa)
        FROM
            user_profile as b
        WHERE
            a.university = b.university
    )
ORDER BY
    a.university;

 外部查询(主查询)

  • SELECT a.device_id, a.university, a.gpa FROM user_profile a
  • user_profile 表中选择列 device_iduniversitygpa

子查询

  • SELECT MIN(b.gpa) FROM user_profile b WHERE a.university = b.university
  • 这个子查询的作用是:
    • user_profile 表(别名为 b)中选择 MIN(b.gpa)
    • MIN(b.gpa) 返回在同一个学校中所有学生的最低 GPA。
    • 子查询中的 WHERE a.university = b.university 是连接条件,它确保子查询只计算当前外部查询正在处理的学校的最低 GPA。

 第二种窗口函数

SELECT device_id, university, gpa
FROM (
    SELECT *,
           ROW_NUMBER() OVER (PARTITION BY university ORDER BY gpa ASC) AS rn
    FROM user_profile
) AS univ_min
WHERE rn = 1
ORDER BY university;

内部查询 

  • ROW_NUMBER() OVER (PARTITION BY university ORDER BY gpa ASC)
    • PARTITION BY university:为每个学校分组(即为每个学校的数据分区)。
    • ORDER BY gpa ASC:在每个学校的数据分组中,按 GPA 升序排序。
    • ROW_NUMBER():为每个分组内的记录分配一个唯一的行号(排名),GPA 最低的记录的行号为 1
  • 结果是一个包含所有原始字段以及一个新字段 rn 的结果集,其中 rn 表示每个学校内的 GPA 排名。

外部查询

SELECT device_id, university, gpa
FROM ( ... ) AS univ_min
WHERE rn = 1
ORDER BY university;
  • WHERE rn = 1
    • 从内部查询结果中筛选出排名为 1 的记录,即每个学校的最低 GPA 记录。
  • ORDER BY university
    • 对最终结果按学校排序,以便按学校顺序展示最低 GPA 的记录。

 

 SQL34 统计复旦用户8月练题情况

现在运营想要了解复旦大学的每个用户在8月份练习的总题目数和回答正确的题目数情况,请取出相应明细数据,对于在8月份没有练习过的用户,答题数结果返回0.

 

select up.device_id,up.university,
       coalesce(sum(qpd.device_id is not null),0) as question_cnt,
       coalesce(sum(qpd.result ='right'),0) as right_question_cnt

from user_profile as up

left join question_practice_detail as qpd 
on up.device_id=qpd.device_id and month(qpd.date)=8

where up.university='复旦大学'
group by up.university,up.device_id

 

SQL35 浙大不同难度题目的正确率

现在运营想要了解江大学的用户在不同难度题目下答题的正确率情况,请取出相应数据,并按照准确率升序输出。

 

 

 

select qd.difficult_level ,
ROUND(sum(case when qpd.result='right' then 1 else 0 end)/count(qpd.device_id),4) as correct_rate
from user_profile as up
inner join question_practice_detail as qpd on up.device_id=qpd.device_id
inner join  question_detail as qd on qd.question_id=qpd.question_id
where up.university='浙江大学'
group by qd.difficult_level
order by correct_rate;
select qd.difficult_level,
sum(if(qpd.result='right',1,0))/count(qpd.device_id) as correct_rate

from question_practice_detail as qpd 
left join user_profile as up on up.device_id=qpd.device_id
left join question_detail as qd on qd.question_id=qpd.question_id
where up.university='浙江大学'
group by qd.difficult_level
order by correct_rate asc;

 

SQL36 查找后排序

现在运营想要取出用户信息表中的用户年龄,请取出相应数据,并按照年龄升序排序。

select 	device_id,age from user_profile order by age;

 

SQL37 查找后多列排序

现在运营想要取出用户信息表中的年龄和gpa数据,并先按照gpa升序排序,再按照年龄升序排序输出,请取出相应数据。

order by +属性+后面不写默认为升序

select device_id,gpa,age from user_profile order by gpa,age;
select device_id,gpa,age from user_profile order by gpa asc,age asc ;
select device_id,gpa,age from user_profile order by gpa,age asc ;

SQL38 查找后降序排列

现在运营想要取出用户信息表中对应的数据,并先按照gpa、年龄降序排序输出,请取出相应数据。

select device_id,gpa,age from user_profile order by gpa desc,age desc;

SQL39 21年8月份练题总数

现在运营想要了解2021年8月份所有练习过题目的总用户数和练习过题目的总次数,请取出相应结果.

select count(distinct device_id) as did_cnt  ,count(question_id) as question_cnt from question_practice_detail where month(date)=8;
select count(distinct device_id) as did_cnt  ,count(question_id) as question_cnt from question_practice_detail where year(date)='2021' and month(date)='08';
select count(distinct device_id) as did_cnt  ,count(question_id) as question_cnt from question_practice_detail where date like "2021-08%";
select count(distinct device_id) as did_cnt  ,count(question_id) as question_cnt from question_practice_detail where date_format(date,'%Y-%m')='2021-08';

;