0
点赞
收藏
分享

微信扫一扫

避免重复扣款:分布式支付系统的幂等性原理与实践

进击的铁雾 2024-01-10 阅读 7

SQL练习题解

一.单表查询(非技术快速入门)

1.基础查询

SQL1 查询所有列

SELECT id, device_id, gender, age, university, province FROM user_profile;

SQL2 查询多列

SELECT device_id, gender, age, university from user_profile

SQL3 查询结果去重

select distinct university from user_profile;

SQL4 查询结果限制返回行数

select device_id from user_profile limit 2

SQL5 将查询后的列重新命名

select device_id as user_infos_example from user_profile limit 2 offset 0

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

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

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

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

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

select device_id, gender, age from user_profile where age between 20 and 23
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 <> '复旦大学';
SELECT device_id,gender,age,university from user_profile where university not in ('复旦大学');
## 模糊查询
SELECT device_id,gender,age,university from user_profile where university not like '%复旦%';

SQL10 用where过滤空值练习

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 != ''

SQL11找到男性且GPA在3.5以上(不包括3.5)的用户

select device_id, gender, age, university, gpa from user_profile where gpa > 3.5 AND gender = 'male'

SQL12 找到学校为北大或GPA在3.7以上(不包括3.7)的用户

select device_id, gender, age, university, gpa from user_profile where university = '北京大学' or gpa > 3.7

SQL13 找到学校为北大、复旦和山大的同学

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

SQL14 找到gpa在3.5以上(不包括3.5)的山东大学用户 或 gpa在3.8以上(不包括3.8)的复旦大学同学

--时间长
select device_id,gender,age,university,gpa from user_profile where university='山东大学' and gpa>3.5 or university='复旦大学' and gpa>3.8
-- 子查询,麻烦, 但时间短
select device_id,gender, age,university,gpa from user_profile 
where device_id in (select device_id from user_profile where university = '山东大学' and gpa > 3.5) 
or device_id in (select device_id from user_profile where university = '复旦大学' and gpa > 3.8)

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

select device_id,age,university from user_profile where university like '%北京%'

SQL16 复旦大学学生gpa最高值

select gpa from user_profile where university = '复旦大学' order by gpa desc limit 1
select max(gpa) as gpa from user_profile where university = '复旦大学' 

SQL17 男性用户有多少人以及他们的平均gpa是多少

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

SQL18 分组计算练习题

select gender, university, 
	count(device_id) as user_num,
	round(avg(active_days_within_30), 1) as avg_active_day, 
	round(avg(question_cnt), 1) as avg_question_cnt 
from user_profile 
group by gender, university

SQL19 分组过滤练习题

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

SQL20 分组排序练习题

select 
    university,
    round(avg(question_cnt), 4) as avg_question_cnt 
from user_profile
group by university
order by avg_question_cnt asc

二.多表查询

(说在前面)复杂SQL的三段式结构

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

# 第一段:select选择字段,含原生字段及构造字段,
#其中构造的过程中常用sum count round +-*/ 等函数及运算表达式
select
    university,
    difficult_level,
    round(count(qpd.question_id) / count(distinct qpd.device_id),4) as avg_answer_cnt

# 第二段:from选择表格,含合并表格操作
from question_practice_detail as qpd
    join user_profile as up
        on up.device_id=qpd.device_id
    join question_detail as qd
        on qd.question_id=qpd.question_id

# 第三段:数据操作段,含 分组/排序/筛选/取指定行数等操作
group by university,difficult_level;


多表查询方法一: 左连接 内连接 右连接 左外连接 右外连接

  • 技术上:
    在这里插入图片描述
  • 业务上:
    业务上多表查询的时候选择哪种取决于你想要保留什么:
    • 想要左表中的所有数据----左连接
    • 想要右表中的所有数据----右连接
    • 想要左右两张表都存在的特殊数据----内连接
    • 只想要左边的且其所有字段都不为null----左外连接
    • 只想要右边的且其所有字段都不为null----右外连接

多表查询方法二:子查询

类似下面这种方式就是嵌套子查询

select device_id,gender, age,university,gpa from user_profile 
where device_id in (select device_id from user_profile where university = '山东大学' and gpa > 3.5) 
or device_id in (select device_id from user_profile where university = '复旦大学' and gpa > 3.8)
  • 什么时候多表查询不能用子查询
    例如SQL22题中universityround(count(question_id) / count(distinct qpd.device_id), 4)这两个字段不在同一张表里, 必须靠链接两张表生成中间表,在中间表中查询;
    因此不能用子查询了,如果两个字段在同一张表的话就可以用子查询类似device_id in (select device_id from xx where ....)

非聚合字段和聚合函数同时出现,要用group by

什么是非聚合字段

  • 在MySQL中,非聚合字段指的是不参与聚合函数计算的字段。我们有一个学生表,其中包含学生的姓名、年龄、性别、班级等信息,我们需要统计每个班级的学生数量,那么班级字段就是聚合字段,而姓名、年龄、性别等字段就是非聚合字段。

  • 非聚合字段的作用非聚合字段在实际应用中非常重要,它们可以用于数据的筛选、排序和分组等操作。我们需要查询年龄大于18岁且性别为女性的学生信息,那么年龄和性别字段就是非聚合字段,在查询语句中需要使用WHERE子句进行筛选。

  • 如何使用非聚合字段在MySQL中,使用非聚合字段的方法非常简单,只需要在SELECT语句中将需要查询的字段列出即可。我们需要查询学生表中的姓名、年龄和性别字段,那么查询语句如下:SELECT 姓名,年龄,性别 FROM 学生表;如果需要对查询结果进行排序,可以使用ORDER BY子句,例如按照年龄从小到大排序:SELECT 姓名,年龄,性别 FROM 学生表 ORDER BY 年龄 ASC;如果需要对查询结果进行分组,可以使用GROUP BY子句,例如按照班级分组统计学生数量:SELECT 班级,COUNT(*) FROM 学生表 GROUP BY 班级;

  • 总结:非聚合字段在MySQL中的作用非常重要,它们可以用于数据的筛选、排序和分组等操作。在使用非聚合字段时,只需要在SELECT语句中将需要查询的字段列出即可,同时可以使用ORDER BY和GROUP BY子句对查询结果进行排序和分组。

非聚合字段和聚合函数同时出现要使用group by

select s.s_id,avg(s.s_score) as avgscore from score s group by s_id

只有聚合函数时,不用group by

select avg(s.s_score) as avgscore from score s

(2表))SQL21 浙江大学用户题目回答情况(含on 和 where的区别)

在多表查询时,on和where都表示筛选条件,on先执行where后执行
区别:
外连接时,on条件是在生成临时表时使用的条件,它不管on中的条件是否为真,都会返回左边表中的记录。而where条件是在临时表生成好后,再对临时表进行过滤的条件。
下面这题是内连接,因此on和where的运行结果相同
链接

--内连接法
select 
    qpd.device_id,
    qpd.question_id,
    qpd.result
from question_practice_detail as qpd inner join user_profile as up
on up.device_id = qpd.device_id and up.university='浙江大学'
order by qpd.question_id asc
--子查询法
select 
    device_id,
    question_id,
    result
from question_practice_detail 
where device_id in(
    select device_id from user_profile
    where university='浙江大学'
) 

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

链接

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

本题universityround(count(question_id) / count(distinct qpd.device_id), 4)这两个字段不在同一张表里, 必须靠链接两张表生成中间表,在中间表中查询;
因此不能用子查询了,如果两个字段在同一张表的话就可以用子查询类似device_id in (select device_id from xx where ....)

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

重命名字段或表的时候用不用as都行:
例如重命名表的时候:user_profile as upuser_profile up都行
例如重命字段的时候:university as uuniversity u都行

----连接三张表, 这里用left join或join(inner join)或right join都行, 因为两边每个id都有, 不存在有一行其他字段为null的情况;
select 
    university,
    difficult_level,
    round(count(qpd.question_id) / count(distinct qpd.device_id), 4) as avg_answer_cnt
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
group by university, difficult_level
----直接暴力用where
SELECT 
    university,
    difficult_level,
    COUNT(q_p.question_id) / COUNT(DISTINCT q_p.device_id) avg_answer_cnt
FROM user_profile u,
     question_detail q,
     question_practice_detail q_p
WHERE
    u.device_id = q_p.device_id
    and q_p.question_id = q.question_id
GROUP BY
    university,difficult_level;

题目整理

1.字符匹配

一般形式为:

例23.查询学生表中姓‘张’的学生的详细信息。

SELECT * FROM 学生表 WHERE 姓名 LIKE ‘张%

例24.查询姓“张”且名字是3个字的学生姓名。

SELECT * FROM 学生表 WHERE 姓名 LIKE '张__’

如果把姓名列的类型改为nchar(20),在SQL Server 2012中执行没有结果。原因是姓名列的类型是char(20),当姓名少于20个汉字时,系统在存储这些数据时自动在后边补空格,空格作为一个字符,也参加LIKE的比较。可以用rtrim()去掉右空格。

SELECT * FROM 学生表 WHERE rtrim(姓名) LIKE '张__'

例25.查询学生表中姓‘张’、姓‘李’和姓‘刘’的学生的情况。

SELECT * FROM 学生表 WHERE 姓名 LIKE '[张李刘]%

例26.查询学生表表中名字的第2个字为“小”或“大”的学生的姓名和学号。

SELECT 姓名,学号 FROM 学生表 WHERE 姓名 LIKE '_[小大]%'

例27.查询学生表中所有不姓“刘”的学生。

SELECT 姓名 FROM 学生 WHERE 姓名 NOT LIKE '刘%

例28.从学生表表中查询学号的最后一位不是2、3、5的学生信息。

SELECT * FROM 学生表 WHERE 学号 LIKE '%[^235]'
举报

相关推荐

分布式幂等性解决方案

0 条评论