牛客网SQL刷题笔记总结
非技术快速入门
1.基础查询
(1)基础查询
查询单列:查询所需的列名写在 SELECT 关键字之后,FROM 关键字指出从哪个表中查询数据。
select device_id from user_profile
查询多个列:唯一的不同是必须在SELECT 关键字后给出多个列名,列名之间必须以逗号分隔。
select device_id,gender,age,university from user_profile
查询所有列:在实际列名的位置使用星号(*)通配符
select * from user_profile
(2)简单处理查询结果
查询结果去重:distinct 关键字加在去重字段前
select distinct university from user_profile
查询结果限制返回行数:limit语句限制返回结果行数。limit语句一般加在SQL语句末尾,并且与数字搭配,写作limit n,n代表想要限制返回的行数。
select device_id from user_profile limit 2
查询后的列重命名:列重命名的语法 -- 'as'
select device_id as user_infos_example from user_profile limit 2
2.条件查询
(1)基础操作符
where语句:where语句限制条件对数据进行过滤
select device_id,university from user_profile where university = '北京大学'
不等于号:< > 或 !=
select device_id,gender,age,university from user_profile where age>24
select device_id,gender,age,university from user_profile
where university !='复旦大学'
范围值:范围值限制方法为between n1 and n2,n1和n2为要限制的区间范围,需要注意两点:
- 一是 and 之前的值 需要小于and 之后的值,不然查询会返回空结果。
- 二是在hive sql中结果会包括两端值,即如果语句写为 betwen 10 and 20, 那么结果中会包括取值等于10或20的数据。
select device_id,gender,age from user_profile where age between 20 and 23
空值:当一个字段不包括任何值时,称其包含空值 NULL
对空值的判断:特殊的WHERE子句,IS NULL 或 IS NOT NULL
select device_id,gender,age,university from user_profile where age is not null
(2)高级操作符
AND操作符:在过滤数据时如果我们想结果同时满足多个条件,可以使用 AND 操作符给 WHERE子句附加条件
select device_id,gender,age,university,gpa from user_profile
where gender='male' and gpa>3.5
OR操作符:在过滤数据时如果我们想要结果只需满足多个条件中的一个,可以使用OR操作符对条件进行连接
select device_id,gender,age,university,gpa from user_profile
where university='北京大学' or gpa>3.7
IN 和 Not IN:IN 操作符用来指定条件范围,范围中的每个条件都可以进行匹配。IN 取 一组由逗号分隔、括在圆括号中的合法值。WHERE 子句中的 NOT 操作符有且只有一个功能,那就是否定其后所跟的任何条件。
select device_id,gender,age,university,gpa from user_profile
where university in ('北京大学','复旦大学','山东大学')
操作符混合运用:两者优先级的问题, SQL在处理 OR操作符前,优先处理 AND 操作符。
select device_id,gender,age,university,gpa from user_profile
where gpa>3.5 and university = '山东大学' or gpa>3.8 and university = '复旦大学'
Like操作符——模糊匹配
Like操作符需要和通配符结合使用,一般最常用的通配符是 %, 在搜索串中,%表示任何字符出现任意次数。使用两个通配符,它们位于检索词的两端,%北京% 标识匹配任何位置上包含文本 北京的值
select device_id,age,university from user_profile
where university like '%北京%'
(3)基础排序
单列排序:ORDER BY 子句取一个或多个列的名字,据此对输出进行排序。
select device_id,age from user_profile order by age
多列排序:按多个列排序,指定列名,列名之间用逗号分开即可,在排序时会按照列给出的先后顺序依次排序。
select device_id,gpa,age from user_profile
order by gpa,age
升序降序:在默认情况下,ORDER BY会对数据进行升序排序(asc)。为了进行降序排序, 必须指定desc 关键字。desc关键字只应用到直接位于其前面的列名。也就是说如果我们SQL语句写的是 Order By age desc,gpa,那么排序将首先按照age降序排序序,再按照gpa升序排序输出。
select device_id,gpa,age from user_profile
order by gpa desc,age desc
3.高级查询
(1)计算函数
AVG:AVG()为平均值函数,可用来返回所有列的平均值,也可以用来返回特定列或行的平均值。
COUNT:COUNT()函数为计数函数,可利用 COUNT()确定表中行的数目或符合特定条件的行的数目。使用 COUNT(*)对表中行的数目进行计数,不管表列中包含的是空值(NULL)还是非空值。 使用 COUNT(column)对特定列中具有值的行进行计数,忽略 NULL 值 。
MAX:MAX()返回指定列中的最大值。MAX在使用时,()需指定要返回最大值的列名
select max(gpa) as gpa from user_profile where university='复旦大学'
MIN:返回指定列的最小值。MIN()也需要求指定列名
SUM:SUM()用来返回指定列值的和(总计)。
取整函数:round(value,n),其中 value代表想要限制小数位数的字段,n代表想要限制的小数位数。
select count(gender) as male_num, round(avg(gpa),1) as avg_gpa
from user_profile where gender='male'
(2)分组查询
分组计算:在使用Group by时,有一些事项需要注意:
1. GROUP BY 子句可以包含任意数目的列,因而可以对分组进行嵌套, 更细致地进行数据分组。
2. 除聚集计算语句外,SELECT 语句中的每一列都必须在 GROUP BY 子句 中同时给出。
3. 如果分组列中包含具有 NULL 值的行,则 NULL 将作为一个分组返回。 如果列中有多行 NULL 值,它们将分为一组。
4. GROUP BY 子句必须出现在 WHERE 子句之后,ORDER BY 子句之前。
select gender,university,count(device_id) as user_num,avg(active_days_within_30) as avg_active_days,avg(question_cnt) as avg_question_cnt
from user_profile
group by gender,university
分组过滤
除了能用 GROUP BY 分组数据外,SQL 还允许在分组的结果下进行过滤,分组查询的结果不能简单的使用Where语句进行过滤,而需要使用专门的Having语句。
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后面不能加聚合函数!!!!! 以下表示错误
where sum(item_price*quantity)>=1000
having 必须在 group by 之后
select distinct order_num,sum(item_price*quantity) as total_price
from OrderItems
group by order_num
having sum(item_price*quantity)>=1000
order by order_num
分组排序 :Order By
select university,avg(question_cnt) as avg_question_cnt
from user_profile
group by university
order by avg_question_cnt
4.多表查询
(1)子查询
子查询(subquery),即 嵌套在其他查询中的查询。
select device_id,question_id,result
from question_practice_detail
where device_id in (select device_id from user_profile where university='浙江大学'
)
order by question_id
(2)链接查询
左链接 (左外连接),其语句为Left join .. on
左连接的定义:是以左表为基础,根据ON后给出的两表的条件将两表连接起来。结果会将左表所有的查询信息列出,而右表只列出ON后条件与左表满足的部分。在使用Left Join时注意要点:
- 在使用Left join 时,写在前面的表为匹配时的底表,使用on给出匹配条件,匹配条件可以不唯一。(在写表与表之间的链接关系时,大多数情况下都必须要限制匹配条件,如果在匹配时没用限制匹配条件,这时就会导致笛卡尔积。)
- 在表匹配时,一般我们会将要匹配的两段查询用括号括起来,并在括号末尾给予一串字母,作为表的别名。
- 在使用on写匹配条件时,如果两个表中有字段名称一样,需要用 表名.字段的写法指 出该字段取自哪一个表,在最终Select语句输出时同理,可以看到设备ID最终输出的写法a.device_id,因为device_id同时存在于两个表中,我们这里指定要用a表中 的device_id列来输出。
select university,difficult_level,round(count(qpd.question_id) / count(distinct qpd.device_id),4) as avg_answer_cnt
from question_practice_detail as qpdleft join user_profile as up
on qpd.device_id=up.device_id
left join question_detail as qd
on qpd.question_id=qd.question_idgroup by university,difficult_level
右链接
右向外联接是左向外联接的反向联接,是以右表为基础,返回右表的所有行,在实际使用中,一般使用Left join就可以满足需求。
内链接
内连接是A表的所有行和B表的所有行在指定条件下得到的交集,所用到的语句为Join
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 university,difficult_level,round(count(qpd.question_id) / count(distinct qpd.device_id) ,4) as avg_answer_cnt
from question_practice_detail as qpdinner join user_profile as up
on qpd.device_id=up.device_id and up.university='山东大学'
inner join question_detail as qd
on qpd.question_id=qd.question_idgroup by difficult_level
(3)组合查询
SQL 也 允许执行多个查询(多条 SELECT 语句),并将结果作为一 个查询结果集返回。这些组合查询通常称为并(union)或复合查询 (compound query)。
union:可给出多条 SELECT 语句,将它们的结果组合成一个结果集。UNION 默认从查询结果集中自动去除了重复的行
union all:不去重的返回所有的匹配行
select device_id,gender,age,gpa from user_profile
where university='山东大学'union allselect device_id,gender,age,gpa from user_profile
where gender='male'
5.必会的常用函数
(1)条件函数
IF 条件函数
IF函数是最常用到的条件函数,其写法为 if(x=n,a,b),x=n代表判断条件,如果x=n时,那么结果返回a,否则返回b。
select if(age<25 or age is null,'25岁以下','25岁及以上') as age_cut,count(*) as number
from user_profile
group by age_cut
Case when
case when与if的作用基本相同,也是按照条件更换列中的内容,区别是case when可以对多个条件进行转换,注意结尾需要加end作为结束
CASE 测试表达式
WHEN 简单表达式1 THEN 结果表达式1
WHEN 简单表达式2 THEN 结果表达式2…
WHEN 简单表达式n THEN 结果表达式n
[ ELSE 结果表达式n+1 ]
END
select case when age<25 or age is null then '25岁以下'else '25岁及以上'end as age_cut,count(*) as number
from user_profile
group by age_cut
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
from user_profile
(2)日期函数
时间戳-日期格式转化
from_unixtime可以将时间戳转换成日期
from_unixtime(time,'yyyy-MM-dd') as time
unix_timestamp可以将日期转换回时间戳
from_unixtime('2021-08-01','yyyy-MM-dd') as time
年月日截取
SQL为此提供了对应的年、月、日提取函数,分别为year(),month(),day()。
year('2021-08-01'),month('2021-08-01'),day('2021-08-01')
日期差计算
datedff
datediff的作用为计算两个日期之间的天数间隔,语法为datediff(date1,date2),返回起始时间 date1 和结束时间 date2 之间的天数,date1大于date2的情况下,返回的天数为正数,date1小于date2的情况下,返回的天数为负数。
datediff('2021-08–09','2021-08-01')
date_sub
语法为date_sub (string startdate, interval int day) ,返回开始日期startdate减少days天后的日期。
date_sub('2021-08–09',interval 8 day)
date_add
语法为date_add(string startdate, interval int day) ,返回开始日期startdate增加days天后的日期
date_add('2021-08–01',interval 8 day)
selectday(date) as day,count(question_id) as question_cnt
from question_practice_detail
where month(date)=8 and year(date)=2021
group by date
(3)文本函数
长度 —length
length函数返回文本字段中值的长度
连接 —concat
CONCAT函数用于将两个或多个字符串连接起来,形成一个单一的字符串
分割 —subtring_index
SUBSTRING_INDEX函数用于将字符串依据某个指定分隔符进行切分,并返回指定位置分隔符前的字符。(字段分割符,位置)负数位置代表从后向前取,-1代表最后一位
select SUBSTRING_INDEX('180,78kg',',','2') as height
select substring_index(profile,',',-1) as gender,count(*) as number
from user_submit
group by gender
select substring_index(substring_index(profile,',',3),',',-1) as age,count(*) as number
from user_submit
group by age
定位 —instr
instr(substr,str):返回substr字符串在str里第一次出现的位置,从1开始,没有则返回0
截取 —substring
substr(string A,int start,int len),返回字符串A从下标start位置开始,长度为len的字符串
substring(string A,int start),在不指定返回字符串长度的情况下,返回字符串A从下标start位置到结尾的字符串
select substring(‘bacda’,2,2)
select substring(‘bacda’,2)
upper表示将字符串大写
select cust_id,cust_name,upper(concat(substring(cust_contact,1,2),substring(cust_city,1,3))) as user_login
from Customers
(4)窗口函数
desc代表降序排列
窗口函数
函数为先分组再排序, row_number() over (partition by col1 order by col2),表示根据col1分组,在分组内部根据col2排序
窗口函数() over (partition by 用于分组的列名order by 用于排序的列名)
窗口函数,比如rank, dense_rank, row_number等
- rank 如果有并列名次的行,会占用下一名次的位置 1 1 3
- dense_rank 如果有并列名次的行,不占用下一名次的位置 1 1 2
- row_number 如果有并列名次的行,也不考虑并列名次的情况 1 2 3
select device_id,university,gpa
from(select device_id,university,gpa,row_number() over (partition by university order by gpa) as rkfrom user_profile) as up
where up.rk=1
6.综合练习
select up.device_id,university,count(question_id) as question_cnt,sum(if(qpd.result='right',1,0)) as right_question_cnt
from user_profile as upleft join question_practice_detail as qpdon qpd.device_id=up.device_id and month(qpd.date)=8
where university='复旦大学'
group by up.device_id
select qd.difficult_level,round(sum(if(qpd.result='right',1,0))/ count(qpd.result),4) as correct_rate
from user_profile as up
inner join question_practice_detail as qpd
on up.device_id=qpd.device_id and up.university='浙江大学'
inner join question_detail as qd
on qd.question_id=qpd.question_idgroup by qd.difficult_level
order by correct_rate
selectcount(distinct device_id) as did_cnt,count(question_id) as question_cnt
from question_practice_detail
where year(date)='2021' and month(date)='08'
SQL必知必会
SQL35 返回每个顾客不同订单的总金额
select o.cust_id,oi.total_ordered
from (select order_num,sum(item_price*quantity) as total_orderedfrom OrderItemsgroup by order_num
)oi,Orders as o
where oi.order_num=o.order_num
order by total_ordered desc
select o.cust_id,sum(oi.item_price*oi.quantity) as total_ordered
from Orders as oleft join OrderItems as oi
on oi.order_num=o.order_numgroup by o.cust_id
order by total_ordered desc
SQL36 从 Products 表中检索所有的产品名称以及对应的销售总数
select prod_name,(select sum(quantity) as quant_soldfrom OrderItemswhere OrderItems.prod_id=Products.prod_id)
from Products
select prod_name,sum(o.quantity) as quant_sold
from OrderItems as o,Products as p
where o.prod_id=p.prod_id
group by prod_name
SQL38 返回顾客名称和相关订单号以及每个订单的总价
注意两个分组
select c.cust_name,o.order_num,sum(oi.quantity*oi.item_price) as OrderTotal
from Customers as c
inner join Orders as o
on c.cust_id=o.cust_id
inner join OrderItems as oi
on oi.order_num=o.order_numgroup by c.cust_name,o.order_num
order by c.cust_name,o.order_num
SQL39 确定哪些订单购买了 prod_id 为 BR01 的产品(二)
select cust_id,order_date
from Orders
where order_num in (select order_num from OrderItems where prod_id='BR01') order by order_date
select cust_id,order_date
from Orders
inner join OrderItems
on Orders.order_num=OrderItems.order_num
where prod_id='BR01'order by order_date
SQL进阶挑战
1.增删改操作
2.表和索引操作
3.聚合分组查询
4.多表查询
(1)嵌套子查询
SQL20 月均完成试卷数不小于3的用户爱作答的类别
select tag,count(exam_id) as tag_cnt
from exam_record
left join examination_info using(exam_id)
where uid in(select uidfrom exam_recordwhere submit_time is not nullgroup by uidhaving count(exam_id)/count(distinct date_format(submit_time,'%Y%m'))>=3)
group by tag
order by tag_cnt desc
SQL21 试卷发布当天作答人数和平均分
select exam_id,count(distinct uid) as uv,round(avg(score),1) as avg_score
from exam_record
where (exam_id,date(start_time)) #筛选发布当天的作答记录in(select exam_id,date(release_time) #获取试卷ID和发布日期from examination_info where tag='SQL')and uid in(select uid from user_info where level>5)
group by exam_id
order by uv desc,avg_score
(2)合并查询
SQL23 每个题目和每份试卷被作答的人数和次数
方法一:用tid字段的左边第一个数来排序
select exam_id as tid,count(distinct exam_record.uid) as uv,count(*) as pv
from exam_record
group by exam_id
union
select question_id as tid,count(distinct practice_record.uid) as uv,count(*) as pv
from practice_record
group by question_idorder by left(tid,1) desc,uv desc,pv desc;
方法二:union后的排序问题,order by子句只能在最后一次使用。 如果想要在union之前分别单独排序,那么需要这样:
select * from
( select * from t1 order by 字段 ) newt1 # 一定要对表重新命名,否则报错
union
select * from
( select * from t2 order by 字段 ) newt2
select * from
( select exam_id as tid,count(distinct exam_record.uid) as uv,count(*) as pv
from exam_record
group by exam_id
order by uv desc,pv desc ) t1 # 一定要对表重新命名,否则报错
union
select * from
( select question_id as tid,count(distinct practice_record.uid) as uv,count(*) as pv
from practice_record
group by question_id
order by uv desc,pv desc ) t2
SQL24 分别满足两个活动的人
select uid,'activity1' as activity
from exam_record
where year(submit_time)=2021
group by uid
having min(score)>=85union allselect uid,'activity2' as activity
from exam_record
join examination_info using(exam_id)
where year(submit_time)=2021 and difficulty='hard' and score>80 and timestampdiff(minute,start_time,submit_time)<duration/ 2order by uid
(3)连接查询
5.窗口函数
(1)专用窗口函数
SQL27 每类试卷得分前3名
对每类标签使用分组聚合排名。知识点:row_number() over partition by 排名优先级先是每个用户的最大得分降序,然后是每个用户的最低得分降序,最后用户ID降序。知识点:order by、min()、max()
见这种近几、连续、每类前几、各个前几直接考虑窗口函数,这里说下常用的几个:
窗口函数语法都是一样的:
<窗口函数> OVER ( partition by <用于分组的列名> order by <用于排序的列名>)
1)窗口函数:有三种排序方式
- rank() over() 1 2 2 4 4 6 (计数排名,跳过相同的几个,eg.没有3没有5)
- row_number() over() 1 2 3 4 5 6 (赋予唯一排名)
- dense_rank() over() 1 2 2 3 3 4 (不跳过排名,可以理解为对类别进行计数)
2)聚合函数:通常查找最大值最小值的时候,首先会想到使用聚合函数。
a.group by的常见搭配:常和以下聚合函数搭配
- avg()-- 求平均值
- count()-- 计数
- sum()-- 求和
- max() -- 最大值
- min()-- 最小值
b.group by 的进阶用法,和 with rollup 一起使用。
3)左右连接
左连接:表1 left join 表2 on 表1.字段=表2.字段 (以表1为准,表2进行匹配)
右连接:表1 right join 表2 on 表1.字段=表2.字段 (以表2为准,表1进行匹配)
全连接:表1 union all 表2 (表1 和表2的列数必须一样多,union 去除重复项,union all 不剔除重复项)
内连接:表1 inner join 表2(取表1和表2相交部分)
外连接:表1 full outer join 表2 (取表1和表2不相交的部分)
select tag,uid,ranking
from (select tag,e_r.uid,row_number() over (partition by tag order by tag,max(score) desc,min(score) desc,e_r.uid desc) as rankingfrom exam_record e_r join examination_info e_i using(exam_id)group by tag,e_r.uid
)ranktable
where ranking <=3
SQL30 近三个月未完成试卷数为0的用户完成情况
select uid, count(score) as exam_complete_cnt
from(select uid,start_time,score,dense_rank() over (partition by uid order by date_format(start_time,'%Y%m') desc) as recent_monthsfrom exam_record
)table1
where recent_months<=3
group by uid
having count(score) = count(uid)
order by exam_complete_cnt desc,uid desc
(2)聚合窗口函数
聚类窗口函数用法和GROUP BY 函数类似。
- MIN() OVER() : 不改变表结构的前提下,计算出最小值
- MAX() OVER(): 不改变表结构的前提下,计算出最大值
- COUNT() OVER(): 不改变表结构的前提下,计数
- SUM() OVER(): 不改变表结构的前提下,求和
- AVG() OVER(): 不改变表结构的前提下,求平均值
SQL33 对试卷得分做min-max归一化
select uid,exam_id,round(avg(max_min),0) as avg_new_score
from(select uid,exam_id,score,if(max_x = min_x, score, 100*(score-min_x)/ (max_x-min_x)) as max_minfrom(select uid,e_r.exam_id as exam_id,score,min(score) over (partition by exam_id) as min_x,max(score) over (partition by exam_id) as max_xfrom exam_record e_r join examination_info e_i using(exam_id)where difficulty = 'hard' and score is not NULL)table1
)table2
group by exam_id,uid
order by exam_id,avg_new_score desc
SQL34 每份试卷每月作答数和截止当月的作答总数
select exam_id,date_format(start_time,'%Y%m') as start_month,count(start_time) as month_cnt,sum(count(start_time)) over (partition by exam_id order by date_format(start_time,'%Y%m')) as cum_exam_cnt
from exam_record
group by exam_id, start_month;
6.其他常用操作
(1)空值处理
SQL37 0级用户高难度试卷的平均用时和平均得分
未完成的默认试卷最大考试时长和0分处理
对空值的处理有两种方法
#方法
1
:coalesce(A,B),如果A为空则返回B,不为空则返回A
#方法
2
:if(A is NULL ,B,C)如果A为空则返回B,不为空则返回C
select uid,round(avg(new_score),0) as avg_score,round(avg(cost_time),1) avg_time_took
from (select e_r.uid as uid,if(score is NULL,0,score) as new_score,if(submit_time is NULL,duration,timestampdiff(minute,start_time,submit_time)) as cost_timefrom exam_record e_r join examination_info e_i using(exam_id)join user_info u_i using(uid)where level=0 and difficulty = 'hard'
)table1
group by uid
(2)高级条件语句
SQL39 筛选昵称规则和试卷规则的作答记录
rlike 后面可以跟正则表达式,正则表达式
"^[0-9]+$"
的意思:
1、字符^ :表示匹配的字符必须在最前边。
例如:^A不匹配“an A”中的‘A’,但匹配“An A”中最前面的‘A’。
2、字符$ :与^类似,匹配最末的字符。
例如:t$不匹配“eater”中的‘t’,但匹配“eat”中的‘t’。
3、字符[0-9] :字符列表,匹配列表中的任一个字符。你可以通过连字符 - 指出字符范围。
例如:[abc]跟[a-c]一样。它们匹配“brisket”中的‘b’和“ache”中的‘c’。
4、字符+ :匹配 + 号前面的字符1次及以上。等价于{1,}。
例如:a+匹配“candy”中的‘a’和“caaaaaaandy”中的所有‘a’。
问题:找到昵称以"牛客"+纯数字+"号"或者纯数字组成的用户对于字母c开头的试卷类别(如C,C++,c#等)的已完成的试卷ID和平均得分,按用户ID、平均分升序排序。
select uid, exam_id, round(avg(score),0) avg_score
from exam_record
where uid in (select uid from user_info where nick_name rlike "^牛客[0-9]+号$" or nick_name rlike "^[0-9]+$") and exam_id in (select exam_id from examination_infowhere tag rlike "^[cC]") and score is not null
group by uid, exam_id
order by uid, avg_score;
(3)限量查询
SQL43 注册当天就完成了试卷的名单第三页
问题:找到求职方向为算法工程师,且注册当天就完成了算法类试卷的人,按参加过的所有考试最高得分排名。排名榜很长,我们将采用分页展示,每页3条,现在需要你取出第3页(页码从1开始)的人的信息。
select uid,level,register_time,max(score) as max_score
from exam_record e_r join examination_info e_i using(exam_id)join user_info u_i using(uid)
where job = '算法' and date(register_time)=date(submit_time) and tag='算法'
group by uid
order by max_score desc limit 6,3
(4)文件转换函数
SQL44 修复串列了的记录
问题: 录题同学有一次手误将部分记录的试题类别tag、难度、时长同时录入到了tag字段,请帮忙找出这些录错了的记录,并拆分后按正确的列类型输出
- 筛选出录错了的记录:where tag like '%,%'
- 提取tag,第一个逗号前的值:substring_index(tag, ',', 1) as tag
- 提取难度,第二个逗号前倒数第一个逗号后:substring_index(substring_index(tag, ',', 2), ',', -1) as difficulty
- 提取时长,最后一个逗号后,并类型转换:cast( substring_index(tag, ',', -1) as decimal ) as duration
select exam_id,substring_index(tag, ',', 1) as tag,substring_index(substring_index(tag, ',', 2), ',', -1) as difficulty,cast( substring_index(tag, ',', -1) as decimal ) as duration
from examination_info
where tag like '%,%';
SQL45 对过长的昵称截取处理
问题: 请输出字符数大于10的用户信息,对于字符数大于13的用户输出前10个字符然后加上三个点号:『...』。
对字符数大于13的用户昵称做处理:char_length(nick_name)>13,
- 前10个字符加上三个点号:concat(substr(nick_name, 1, 10),'...')
select uid, if(char_length(nick_name)>13, concat(substr(nick_name, 1, 10),'...'), nick_name) as nick_name
from user_info
where char_length(nick_name)>10;
SQL46 大小写混乱时的筛选统计
问题:试卷的类别tag可能出现大小写混乱的情况,请先筛选出试卷作答数小于3的类别tag,统计将其转换为大写后对应的原本试卷作答数。
如果转换后tag并没有发生变化,不输出该条结果。
with t_tag_count as(select tag, count(uid) as answer_cntfrom exam_record left join examination_info using(exam_id)group by tag
)select a.tag as tag, b.answer_cnt as answer_cnt
from t_tag_count as a join t_tag_count as b #表t_tag_count进行自连接on upper(a.tag)=b.tag and a.tag!=b.tag and a.answer_cnt < 3 ;
SQL大厂面试真题
1.某音短视频
2.用户增长场景(某度信息流)
3.电商场景(某东商城)
4.出行场景(某滴打车)
5.某宝店铺分析(电商模式)
6.牛客直播课分析(在线教育行业)
7.某乎问答(内容行业)
牛客网SQL刷题笔记总结相关推荐
- 牛客网SQL刷题笔记(MySQL)
牛客网SQL刷题笔记(MySQL) 此博客集合LeetCode.牛客网常见的题型及其解法,侵删 目录 牛客网SQL刷题笔记(MySQL) 类型1:查找排名第几的数据 SQL2 查找入职员工时间排名倒数 ...
- 牛客网java刷题笔记2019-1-4
牛客网java刷题笔记 2019-1-4 1.java中可以用类中构造器调用其他类构造器(这个和C++中构造函数很类似)用于初始化程序变量值, 构造器和方法的区别: 功能和作用的不同 构造器是为了创建 ...
- sql里查询一个组和组的用户数怎么查?_【牛客网SQL刷题】留存率怎么算?
抽空刷了牛客网SQL实战72题,最后几道以牛客网为例的题目还挺有挑战性,在此记录 统计时间段新用户次日留存率 每日的次日留存率 每日的新用户数 每日新用户的次日留存 求新登录用户次日留存 表login ...
- 牛客网SQL刷题问题汇总
目录 1.选取字段为[奇数或偶数问题] 2.[排序问题] 3.MySQL[新建表.修改表] 4.对于表批量[插入数据],如果数据已经存在,则忽略 5.新建一个表,表中字段内容从另一个表导入 6.[索引 ...
- 牛客网SQL刷题四-电商场景(某东商城)
SQL13 计算商城中2021年每月的GMV 数据 DROP TABLE IF EXISTS tb_order_overall; CREATE TABLE tb_order_overall (id I ...
- 牛客网SQL刷题二-某音短视频
SQL1 各个视频的平均完播率 数据 DROP TABLE IF EXISTS tb_user_video_log, tb_video_info; CREATE TABLE tb_user_video ...
- 牛客网Java刷题知识点之关键字static、static成员变量、static成员方法、static代码块和static内部类...
不多说,直接上干货! 牛客网Java刷题知识点之关键字static static代表着什么 在Java中并不存在全局变量的概念,但是我们可以通过static来实现一个"伪全局"的概 ...
- 牛客网Java刷题知识点之构造函数可以调用一般函数,但是一般函数不可以直接调用构造函数...
不多说,直接上干货! 通过 牛客网Java刷题知识点之构造函数是什么.一般函数和构造函数什么区别呢.构造函数的重载.构造函数的内存图解 我们对构造函数有了一个比较清楚的认识,当我们在创建对象时,我们会 ...
- 牛客网Java刷题知识点之Java 集合框架的构成、集合框架中的迭代器Iterator、集合框架中的集合接口Collection(List和Set)、集合框架中的Map集合...
不多说,直接上干货! 集合框架中包含了大量集合接口.这些接口的实现类和操作它们的算法. 集合容器因为内部的数据结构不同,有多种具体容器. 不断的向上抽取,就形成了集合框架. Map是一次添加一对元素. ...
最新文章
- Selenium高亮页面对象
- windows内存管理概述
- python国内谁的书最好看_强烈建议|转行Python最好看一下这篇文章
- 【公共类库】加密解密
- 数据结构与算法--B树原理及实现
- Linux背后的思想
- 飞鸽传书2007绿色版
- 9:04 2009-7-28
- 博客园的博客中插入公式
- Cortex-M3 (NXP LPC1788)之WDT窗口看门狗定时器
- 【编译原理】第三章语法分析
- 一名5年工作经验的程序员应该具备的技能
- 模拟电子技术 项目课 多种波形发生器(方波、三角波、正弦波)
- windows Delete键和Backspace键的区别
- 【寻找最佳小程序】13期:心算练习——寓教于乐,练就小朋友强大的算术能力...
- 双11有哪些好用的降噪蓝牙耳机值得推荐?降噪蓝牙耳机性价比排行
- Oracle数据泵导入导出dmp数据文件详细教程
- intel英特尔无线适配器高级设置
- win10打开蓝牙_这4个Win10新增的快捷键,提高效率必备
- buff系统 游戏中_请问BUFF状态