SQL基础


备注:牛客网的题是按MySQL的

单表查询

1、选择某个字段最大值所在的记录

eg:查找入职最晚员工的所有信息(牛客题号:SQL1)
分析:通过入职时间对整个表降序排列,位于第一个即入职时间最大(最晚)的员工
实现:

select * 
from employees
where hire_date = (select max(hire_date) 
                  from employees)

2、选择某个特定字段所在的记录

eg:查找入职员工时间排名倒数第三的员工所有信息(牛客题号:SQL2)
分析:设想了一种思路(还未实现):首先选出最晚入职的三个员工,在选择其中入职时间最小的,但只通过了一组测试用例

select *
from employees
where hire_date = (select min(hire_date)
                  from employees order by  hire_date desc limit 3);                  

错误原因子查询中不能使用order by
可使用limit子句通过:

select *
from employees
order by  hire_date desc limit 2,1;
//或者写为offset的形式
// order by hire_date limit 2 offset 1;

查看某列的取值范围

SQL3 查询结果去重:https://www.nowcoder.com/practice/82ebd89f12cf48efba0fecb392e193dd?tpId=199&tags=&title=&difficulty=0&judgeStatus=0&rp=0&sourceUrl=%2Fexam%2Foj
可以使用distinct子句或者group by子句

--1、使用distinct子句
 select distinct university from user_profile
 2、使用group by子句
select university from user_profile group by university

在分组结果中增加过滤条件(having子句)

SQL19 分组过滤练习题https://www.nowcoder.com/practice/ddbcedcd9600403296038ee44a172f2d?tpId=199&tags=&title=&difficulty=0&judgeStatus=0&rp=0&sourceUrl=%2Fexam%2Foj

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,
    avg(question_cnt) as avg_question_cnt
from user_profile
    group by university
    order by avg(question_cnt)

字符串截取 substring_index函数

按某分隔符截取或按位置截取

SQL32 截取出年龄

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

多表查询

使用on或where子句基本语法

  1. eg:查找各个部门当前领导当前薪水详情以及其对应部门编号dept_no
    分析: 从建表语句及样例输出可以看出salaries表所有字段都是在结果里的,加上另一个表dept_manager中的dept_no字段即可
select salaries.*,dept_manager.dept_no
from salaries inner join dept_manager
on salaries.emp_no = dept_manager.emp_no
//on换成where也可以
//where salaries.emp_no = dept_manager.emp_no
order by emp_no 
  1. eg:查找所有已经分配部门的员工的last_name和first_name
select e.last_name,e.first_name,d.dept_no
from employees e,dept_emp d
where e.emp_no = d.emp_no

on与and连用注意

SQL24 统计每个用户的平均刷题数
ON子句里条件的作用范围是生成的临时表内,如果后边还加and子句条件去限制,返回的结果就会和join方式、and子句条件涉及的列有关了。注意临时表里的数据到底是什么

--on、and条件有问题导致出现university里有空的
select university,    difficult_level,    round(count(qp.question_id)/count(distinct qp.device_id),4) as avg_answer_cnt
from user_profile u right join question_practice_detail qp
    on u.device_id = qp.device_id
    and u.university = '山东大学'  
inner join question_detail qd
    on qp.question_id = qd.question_id
group by qd.difficult_level,university
--通过的sql
select university,    difficult_level,    round(count(qp.question_id)/count(distinct qp.device_id),4) as avg_answer_cnt
from user_profile u right join question_practice_detail qp
    on u.device_id = qp.device_id
inner join question_detail qd
    on qp.question_id = qd.question_id
    where u.university = '山东大学'
group by qd.difficult_level,university

可以参考博客:MySQL中 left join on 后的 and 条件与 where 中条件的区别

union,union all :去重与否

union all对连接的两表不进行去重

case when子句

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

select device_id,
    gender,
    case when age >= 25 then '25岁及以上'
    when age >= 20 and age < 25 then '20-24岁'--此处直接写成age>=20也可以,已经类似分段了
    when age < 20 then '20岁以下'
    else '其他'
    end age_cut
from user_profile

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

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

或者用if也可以,(已经暗含了age为null的算在25岁以下)

select 
    if(age>=25,"25岁及以上","25岁以下") as age_cut,
    count(*) as number
from user_profile
group by age_cut

特定日期的数据

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

select day(date) as day,    count(*) as question_cnt
from question_practice_detail
where month(date) = 8 and year(date) = 2021
group by 1

本题要注意的地方:

  1. 怎么获取是第几天
  2. 限定日期范围:可以使用like ‘2021-08%’、substring(date,1,7) = ‘2021-08’,regexp ‘2021-08’

关联子查询

子查询里使用到了外层查询的列

select * from table_name t
where column1 > ( select avg(column) from table_name 
				  where column_name = t.columnn_name)

标量子查询

select 和 from中间的就是标量子查询

练习在线网站推荐

  1. 力扣https://www.lintcode.com/learn
  2. 牛客https://www.nowcoder.com/exam/oj?page=1&tab=SQL%E7%AF%87&topicId=199
    力扣的教程比较细一点,但看不到其他人的代码(但是牛客网可以,不知道是不是力扣我的账号权限不够),参与感有点弱。

查看官方参考文档

MySQL官方文档

进入MySQL文档中心:https://dev.mysql.com/doc/
在这里插入图片描述
直接点击参考手册进入即可,然后在搜索框里查要看的函数

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值