4h搞定数据库编程常用语法以及牛客题目

这个短文总结了牛客的SQL编程常用的语法和对应例题,答案参考了广大神仙网友们的解答。

本科时候学过数据库,差不多快忘了,有些语法还记得。笔试发现居然考数据库编程,笔试的时候稍微有点卡壳,于是乎用了痛下决心一天之内刷完数据库。
结果花了4小时左右刷完了牛客数据库的题目并做了答案搬运和总结(困难程度的看了看,直接略过了),有些理解不对欢迎大家指正奥。

个人感觉数据库编程比c++真的简单好多啊(也有可能我比较菜),刷题速度飞起那种。


1. in not in

select device_id,gender,age,university,gpa

from user_profile

where university in ('北京大学','复旦大学','山东大学')

注意: is in

什么时候用 is,表达bool类型的时候

 

2.过滤空值

select device_id,gender,age,university

    from user_profile

        where age is not NULL

 

注意:不能写成age=NULL

 

3.结果去重

select distinct university from user_profile

 

4. 列重命名,只取前两行

 select device_id

from user_profile

as user_infos_example

limit 2

 

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

select device_id,gpa,age

from user_profile

order by gpa asc,age asc

注意:降序 desc

 

6. 现在运营想要找到gpa3.5以上(不包括3.5)的山东大学用户 或 gpa3.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='复旦大学')

 

注意:gpa>3.5 and university is'山东大学' 错误

 

7. 模糊查询like

_ :匹配一个字符 例如:查找姓张且名字为三个字的学生信息 select * from student where name like '张__'

%:匹配0个或多个字符串 例如:查找姓张的学生的信息 select * from student where name like '张%

[]匹配框中的任意一个字符 例如查找姓李、张、宋的学生信息 select * from student where name like '[张李宋]%'

不匹配[]中的字符 例如找出除姓张、唐之外的学生信息 select * from student where name like '[^张唐]%'

查询姓名中第二个字为大或小的学生信息 seletc * from student where name like '_[小大]%'

 

 

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

select device_id,age,university

from user_profile

where university like '%北京%'

 

9. 查找gpa最高

select max(gpa)

from user_profile

where university in('复旦大学')

 

10. 计算男生人数以及平均GPA

问题分解:

(1)限定条件为 男性用户;(2)有多少人,明显是计数,count函数;(3)平均gpa,求平均值用avg函数;

细节:

1)表头重命名,用as语法

2)浮点数的平均值可能小数点位数很多,按照示例保存一位小数,用round函数

select

    count(gender) as male_num,

    round(avg(gpa),1) as avg_gpa

from user_profile

where gender='male'

   

 

11.分组group by

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

select gender,university,

    count(gender) 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

 

13. 聚合之后筛选having

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

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

注意:聚合函数结果作为筛选条件时,不能用where,而是用having语法配合重命名即可

 

14. 聚合之后排序

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

select university,

    avg(question_cnt) as avg_question_cnt

from user_profile

group by university

order by avg_question_cnt asc

 

15.多表查询-子查询

运营想查看所有来自浙江大学的用户题目回答明细情况,请你取出相应数据

select device_id,question_id,result

from question_practice_detail

where device_id in(

    select device_id

    from user_profile

    where university='浙江大学'

)

group by……

 

16. 多表查询-自然连接 JOIN

 

select university,

    round(count(qpd.question_id)/count(distinct qpd.device_id),4)

    as avg_answer_cnt

from user_profile as uf join question_practice_detail as qpd    ///   table1 join table2

    on uf.device_id=qpd.device_id

group by university

 

注意:第二行 qpd.device_id是谁的device_id,如果不加,数据库不知道是哪个表的

 

17. 运营想要计算一些参加了答题的不同学校、不同难度的用户平均答题量,请你写SQL取出相应数据

select university,difficult_level,

    round(count(qpd.question_id)/count(distinct qpd.device_id),4) //必须要加distinct

    as avg_answer_cnt

from user_profile as up

join question_practice_detail as qpd

on up.device_id=qpd.device_id

 

join question_detail as qd

on qd.question_id=qpd.question_id

 

group by university,difficult_level

 

18. 运营想要查看参加了答题的山东大学的用户在不同难度下的平均答题题目数,请取出相应数据

 

select university,difficult_level,

    round(count(qpd.question_id)/count(distinct qpd.device_id),4)

    as avg_answer_cnt

from user_profile as up

join question_practice_detail as qpd

on up.device_id=qpd.device_id

 

join question_detail as qd

on qpd.question_id=qd.question_id

where university='山东大学'

group by difficult_level

 

19. 现在运营想要分别查看学校为山东大学或者性别为男性的用户的device_idgenderagegpa数据,请取出相应结果,结果不去重

 

select device_id,gender,age,gpa

from user_profile

where university='山东大学'

union all   //all不能少

select device_id,gender,age,gpa

from user_profile

where gender='male'

 

注意:不用where or:

第一or去重

第二实际应尽量避免在where子句中使用or来连接条件。使用or可能会使索引失效,从而全表扫描。mysql是有优化器的,处于效率与成本考虑,遇到or条件,索引可能失效

 

20.union union all

1union: 对两个结果集进行并集操作, 不包括重复行,相当于distinct;

union all: 对两个结果集进行并集操作,, 不管是不是重复;

2union: 会对获取的结果进行排序操作

union all: 不会对获取的结果进行排序操作

 

21.时间函数

现在运营想要计算出20218月每天用户练习题目的数量,请取出相应数据。

day(),year(),month()

select

day(date) as day,

count(question_id) question_cnt  //这里没加distinct,因为练习题id可能重复

from question_practice_detail

where year(date)=2021 and month(date)=8

group by day

 

22Case

…………

CASE 测试表达式

WHEN 简单表达式1 THEN 结果表达式1

WHEN 简单表达式2 THEN 结果表达式2

WHEN 简单表达式n THEN 结果表达式n

[ ELSE 结果表达式n+1 ]

END

…………….

Eg:





 

 


23.现在运营想要将用户划分为25岁以下和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

 

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

 

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 as age_cut   //as可以省略

from user_profile

 

25.字符串截取

转自https://www.cnblogs.com/mqxs/p/7380933.html

 

26.

现在运营想要统计每个性别的用户分别有多少参赛者,请取出相应结果

方法一:like

select if(profile like '%female','female','male') as gender,

count(*) as number

from user_submit

group by gender

 

方法二:SUBSTRING_INDEX的写法

select substring_index(profile,',',-1) as gender,

count(*) as number

from user_submit

group by gender

 

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

select device_id,

    substring_index(blog_url,'/',-1) as user_name

from user_submit

 

28.现在运营想要统计每个年龄的用户分别有多少参赛者,请取出相应结果

select

    substring_index(substring_index(profile,',',-2),',',1) as age,

    count(device_id) as number

from user_submit

group by age

 

29.

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

 

注意:gpa最低,看似min(gpa),但是要留意,是每个学校里的最低,不是全局最低。min(gpa)的时候对应同学的ID丢了,直接干是拿不到最低gpa对应的同学ID的;

 

方法一:相关子查询

select

device_id,university,gpa

from user_profile as up

where gpa=(

    select min(gpa)

    from user_profile

    where university=up.university

)

order by university

 

利用相关子查询,把每个学校的最低gpa当作查询条件,去找出每个学校的gpa最低的同学。因为每个学校只有一个gpa最低的同学,所以最后出来的结果不需要再用group by,用order by排序就好。看代码!!

在子查询中,我们利用到了主查询的表,WHERE university = u.university 这个条件使得mysql去主表得每一行进行查询,比如第一行是2138的北京大学的同学,那么子查询会找出所有北京大学的同学,并且找出其中最低得gpa,如果他是最低的那个就留下,不是就下一个。以此类推找出所有大学的最低gpa的同学,最后排序得最终结果。

 

方法二:窗口函数

https://zhuanlan.zhihu.com/p/92654574

select *,

   rank() over (partition by 班级

                 order by 成绩 desc) as ranking

from 班级表

group by分组汇总后改变了表的行数,一行只有一个类别。而partiition by和rank函数不会减少原表中的行数。例如下面统计每个班级的人数。

 

select

device_id,university,gpa

from(select *,

    rank() over (partition by university

                order by gpa asc) as rk

     from user_profile

    ) as a

where a.rk=1

 

外层嵌套要用到内层,内层表必须需要给出声明 as a,不能省略

 

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

子查询:

select

count(distinct device_id) as did_cnt,

count(question_id) as question_cnt

from(select *

     from  question_practice_detail

     where year(date)=2021 and month(date)=8) as a


--------------------------------------补充

插删改操作:http://t.csdn.cn/EAYO2

1.insert 插入

(1)在“Customers”表中插入一条新记录:

INSERT INTO Customers (CustomerName, ContactName, Address, City, PostalCode, Country)

VALUES ('Cardinal', 'Tom B. Erichsen', 'Skagen 21', 'Stavanger', '4006', 'Norway');

(2)仅在指定列中插入数据

INSERT INTO Customers (CustomerName, City, Country)

VALUES ('Cardinal', 'Stavanger', 'Norway');

2.update更新
更新CustomerID = 1的用户名字和城市数据

UPDATE Customers
SET ContactName = 'Alfred Schmidt', City= 'Frankfurt'
WHERE CustomerID = 1;

3.delete删除
(1)从“Customers”表中删除客户“Alfreds Futterkiste”:

DELETE FROM Customers WHERE CustomerName='Alfreds Futterkiste';

(2)删除“Customers”表中的所有行,但不删除该表:

DELETE FROM Customers;


注意:drop是删除整表或者数据库,不能与where连用.....如drop tablex

4.建表
参考:http://t.csdn.cn/XwokH


①使用英文() ,表的名称和字段尽量使用 `` 括起来
②AUTO INCREMENT 自增
③字符串用单引号括起来
④所有的语句用结尾加上 , 最后一句不用加
⑤PRIMARY KEY 主键,一般一个表只有一个唯一的主键。

CREATE TABLE IF NOT EXIST 'student'(
  `id` INT(4) NOT NULL AUTO_INCREMENT COMMENT '学号',   --comment注释,default默认
  `name` VARCHAR(30) NOT NULL DEFAULT '匿名' COMMENT '姓名',
  `pwd` VARCHAR(20) NOT NULL DEFAULT '123456' COMMENT '密码',
  `sex` VARCHAR(2) NOT NULL DEFAULT '女' COMMENT '性别',
  `birthday` DATETIME DEFAULT NULL COMMENT '出生日期',
  `address` VARCHAR (100) DEFAULT NULL COMMENT '家庭地址',
  `email` VARCHAR(50) DEFAULT NULL COMMENT '电子邮箱',
  PRIMARY KEY(`id`)  --主键
)ENGINE=INNODB DEFAULT CHARSET=utf8  --INNODB引擎






全部评论

相关推荐

浪子陪都:简历最优秀的地方放到了后面,国奖,校级奖学金这些是最亮眼的。说明你跟同级别的学生不一样。 建议台灯这个,PCB布局布线这个词汇不专业,业内是PCB Layout,第二,单片机的板子一般不用考虑SI,PI 都是低速信号,只要遵循3W原则就好了。 单片机的项目太low了,技能这块,你要看一下BOSS直聘的招聘要求,按照别人的要求写,一些关键词可以增加你简历被检索到的概率。 主修课程不用写,这个没有人去关注的。
点赞 评论 收藏
分享
评论
7
22
分享

创作者周榜

更多
牛客网
牛客企业服务