数据库练习题(牛客网sql入门篇部分)

Posted 霏ིྀ宇ིྀ

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了数据库练习题(牛客网sql入门篇部分)相关的知识,希望对你有一定的参考价值。

数据库练习题

SQL1:查询结果去重

去重关键字 DISTINCT
select DISTINCT university
from user_profile;

group by 是分组查询
SELECT university 
FROM user_profile GROUP BY user_profile;

SQL2:查询结果限制返回行数

select device_id
from  user_profile 
limit 0,2
select device_id 
from user_profile 
limit 2;
select device_id 
from user_profile 
limit 2 offset 0;
select device_id 
from user_profile 
where id in(1,2);
select device_id 
from user_profile 
where id <=2;
或where id <3;
select device_id 
from user_profile 
where id=1 or id=2;

SQL3:将查询后的列重新命名

select  device_id as user_infos_example 
from  user_profile 
limit 2 
select  device_id as user_infos_example 
from  user_profile 
limit 0,2 
select  device_id as user_infos_example 
from  user_profile 
where id in(1,2);

SQL4:查找学校是北大的学生信息

SELECT device_id,university 
FROM user_profile 
WHERE university LIKE '北京大学%'
SELECT device_id,university
FROM user_profile
WHERE university="北京大学"

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

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

SQL6:从不订购的客户

select c.Name as Customers 
from Customers c 
where c.Id not in (select distinct o.CustomerId from Orders o);

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

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

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

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

SQL10 用where过滤空值练习

过滤空值的三种方法:

(1) Where 列名 is not null

(2) Where 列名 != ‘null’

(3) Where 列名 <> ‘null’

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 <>'null' 正则
SELECT device_id,gender,age,university 
FROM user_profile 
where age !='null' 比较

SQL11 高级操作符练习(1)

现在运营想要找到男性且GPA在3.5以上(不包括3.5)的用户进行调研,请你取出相关数据。

SELECT device_id, gender, age, university,gpa
FROM user_profile
WHERE gpa >3.5 AND gender in('male')
SELECT device_id,gender,age,university,gpa 
FROM user_profile
WHERE gpa>3.5 AND gender IN(SELECT gender FROM user_profile WHERE gender='male')

SQL12 高级操作符练习(2)

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

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

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="山东大学"
select device_id,gender,age,university,gpa
from user_profile
where find_in_set(university,'北京大学,复旦大学,山东大学');

SQL14 操作符混合运用

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

SELECT device_id,gender,age,university,gpa
FROM user_profile
user_profile where gpa > 3.8 and university = '复旦大学' 
UNION
SELECT device_id, gender, age, university,gpa 
from user_profile 
where gpa > 3.5 and university = '山东大学'

SELECT  device_id, gender, age, university,gpa 

from user_profile 

where (gpa > 3.8 and university = '复旦大学') or (gpa > 3.5 and university = '山东大学')
#法1:使用 OR 和 AND 混合运算
SELECT device_id,gender,age,university,gpa 
FROM user_profile
WHERE gpa>3.5 AND university='山东大学' OR gpa>3.8 AND university='复旦大学'
#法2:使用union all(需要排序)
SELECT device_id,gender,age,university,gpa 
FROM user_profile
WHERE gpa>3.5 AND university='山东大学'
UNION ALL
SELECT device_id,gender,age,university,gpa 
FROM user_profile
WHERE gpa>3.8 AND university='复旦大学'
ORDER BY device_id ASC

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

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

select device_id,age,university
from user_profile
where university LIKE '%北京%';
SELECT device_id,age,university
FROM user_profile 
WHERE university regexp "北京";

LIKE 和 REGEXP之间的重要差别

-- LIKE 匹配整个列,如果被匹配的文本在列值中出现,LIKE 将不会找到它,相应的行也不会被返回(除非使用通配符)。而 REGEXP 在列值内进行匹配,如果被匹配的文本在列值中出现,REGEXP 将会找到它,相应的行将被返回,并且 REGEXP 能匹配整个列值(与 LIKE 相同的作用)。

SQL16 查找GPA最高值

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

select max(gpa)
from user_profile
where university = '复旦大学'
select round(max(gpa),1)
from user_profile
where university = '复旦大学'
SELECT gpa
FROM user_profile
WHERE university='复旦大学' 
ORDER BY gpa DESC
LIMIT 0,1
select gpa
from(select gpa,row_number()over(partition by university order by gpa desc) as ranking
from user_profile
where university = '复旦大学') as t
where t.ranking = 1;

SELECT gpa
FROM user_profile
WHERE university ="复旦大学"
ORDER BY gpa DESC
LIMIT 1;

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

select count(gender) as male_num,
Round(avg(gpa),1)as avg_gpa
from user_profile
where gender='male';
select
  count(gender)  male_num,
  round(avg(gpa),1)  avg_gpa
from user_profile GROUP BY gender having gender ='male'
select 
    count(id) male_num,avg(gpa) avg_gpa 
from 
    user_profile 
group by 
    gender 
having 
    gender='male'

SQL18 分组计算练习题

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

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
       
select l.gender,l.university,
      count(gender) as user_num ,
      avg(l.active_days_within_30) as avg_active_day,
      avg(l.question_cnt) as avg_question_cnt
      FROM user_profile l 
      group by l.university ,l.gender
select gender,university,
       count(gender) as user_num,
       ROUND(avg(active_days_within_30),1),
        ROUND(avg(question_cnt),1)
from user_profile
group by gender,universit

SQL19 分组过滤练习题

取出平均发贴数低于5的学校或平均回帖数小于20的学校

聚合函数结果作为筛选条件时,不能用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
# select查询字段中有非聚合函数和聚合函数
# 一定是按照非聚合函数字段进行分组
 
# 按照执行顺序,是from -> where -> group by -> having -> select -> order by -> limit
# 理论上来说,select中的聚合函数字段无法在having中使用,
# 但是mysql会做自动优化的替换,无论定义在哪,聚合的操作执行一次,having里和select里都可以使用

SQL20 分组排序练习题

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

需要单独命名avg_question
select university,
avg(question_cnt) as avg_question_num
from user_profile
group by university
order by avg_question_num
不需要单独命名
select university,avg(question_cnt) 
from user_profile
group by university 
order by avg(question_cnt)

操作能运行成功的原因是 order by后面可以加聚合函数。但要注意,group by后面不可。

有三类后面可以加聚合函数

1、select

2、order by

3、having

由于SQL语句执行顺序如下:
FROM - ON - JOIN - WHERE 
- GROUP BY - WITH - HAVING - SELECT - DISTINCT - ORDER BY - LIMIT

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

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

子查询
select device_id ,question_id,result
from question_practice_detail
where device_id=(
    select device_id 
    from  user_profile
where university="浙江大学"
);
 连接查询
select q.device_id ,q.question_id,q.result
from question_practice_detail AS q,
user_profile as u
where q.device_id=u.device_id 
and university="浙江大学";
 内连接查询
select q.device_id ,q.question_id,q.result
from question_practice_detail AS q inner join
user_profile as u
on  q.device_id=u.device_id 
and university="浙江大学";
使用左外联结查询
select q.device_id,q.question_id,q.result
from question_practice_detail q
left join user_profile u
on q.device_id = u.device_id
where u.university = '浙江大学';
exists 的意思是用于检查子查询是否至少会返回一行数据,该子查询实际上并不返回任何数据,而是返回值True或False
SELECT
device_id,question_id,result
FROM
question_practice_detail q
WHERE
 EXISTS (SELECT
                    device_id
                    FROM
                    user_profile u
                    WHERE q.device_id = u.device_id AND university="浙江大学")
ORDER BY q.question_id

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

SELECT university,
       count(*)/count(DISTINCT q.device_id) avg_answer_cnt
FROM question_practice_detail q
    LEFT JOIN user_profile u ON u.device_id=q.device_id
GROUP by university
select u.university,
count(u.university)/count(DISTINCT u.device_id)as answer
from 
user_profile as u
inner join question_practice_detail as q
on u.device_id=q.device_id
group by u.university;

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

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

select 
     t1.university,
     t3.difficult_level,
     count(t2.question_id)/count(distinct(t2.device_id)) 
     as avg_answer_cnt
from
    user_profile as t1,
    question_practice_detail as t2,
    question_detail as t3
where
     t1.university ="山东大学"
     and t1.device_id =t2.device_id
     and t2.question_id=t3.question_id
group by
 t3.difficult_level;

-- 内连接(inner join)
select
  university,
  difficult_level,
  count(qpd.question_id) / count(DISTINCT qpd.device_id) as avg_answer_cnt
from
  user_profile as u
  inner join question_practice_detail as qpd on u.device_id = qpd.device_id
  inner join question_detail as qd on qpd.question_id = qd.question_id
where
  university = '山东大学'
group by
  difficult_level
select
  t.university,
  t2.difficult_level,
  round(
    count(t1.question_id) / count(distinct t1.device_id),
    4
  ) as avg_answer_cnt
from
  user_profile  t 
   join   question_practice_detail  t1 on t.device_id=t1.device_id
   join    question_detail  t2 on t1.question_id=t2.question_id
where
  t.university = '山东大学'
GROUP BY
  t.university,
  t2.difficult_level
  ORDER BY 
  t.university desc

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

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'

不去重就得用union all,否则可以用union 或者where university = “山东大学” or gender = “male”

SQL61 检索并列出已订购产品的清单

-- 去重
select distinct prod_id from OrderItems
-- 分组
select  prod_id from OrderItems group by prod_id

SQL62检索所有

# 匹配所有列
select * from Customers 
 # 指定列名
select cust_id,  cust_name from Customers

SQL82返回 2020 年 1 月的所有订单的订单号和订单日期

select order_num,order_date
from Orders
where year(order_date)='2020' and month(order_date)= '01'
order by order_date
select *
from Orders
where order_date between '2020-01-01' and '2020-01-31'
order by order_date
select *
from Orders
where order_date like "%2020-01%"
order by order_date asc
select *
from Orders
where order_date regexp('2020-01')
order by order_date 
select
  order_num,
  order_date
from
  Orders
where
  order_date < '2020-02-01 00:00:00'
  and order_date >= '2020-01-01 00:00:00'
order by
  order_date

SQL156 各个视频的平均完播率

问题:计算2021年里有播放记录的每个视频的完播率(结果保留三位小数),并按完播率降序排序

:视频完播率是指完成播放次数占总播放次数的比例。简单起见,结束观看时间与开始播放时间的差>=视频时长时,视为完成播放。

-- 用avg、case when 
SELECT
  t.video_id ,
  ROUND(
    AVG(
      CASE
        WHEN TIMESTAMPDIFF(SECOND, t.start_time, t.end_time) >= duration THEN 1
        ELSE 0
      END
    ),
    3
  ) AS avg_comp_play_rate
FROM
  (
    SELECT *
    FROM
      tb_user_video_log
    WHERE
      YEAR(end_time) = 2021
  ) AS t
  LEFT JOIN tb_video_info t2 ON t.video_id = t2.video_id
GROUP BY
  t.video_id
ORDER BY
  avg_comp_play_rate desc;
select
  a.video_id,
  round(
    sum(
      case
        when diff_time >= duration then 1
        else 0
      end
    ) / count(a.video_id),
    3
  ) as avg_comp
from
  ( 
    select
      *,
      timestampdiff(second, start_time, end_time) as diff_time
    from
      tb_user_video_log
  ) a
  left join tb_video_info b on a.video_id = b.video_id
group by
  video_id
order by
  avg_comp desc
SELECT
  t.video_id ,
  ROUND(
    AVG(
      CASE
        WHEN TIMESTAMPDIFF(SECOND, t.start_time, t.end_time) >= duration THEN 1
        ELSE 0
      END
    ),
    3
  ) AS avg_comp_play_rate
FROM
  (
    SELECT *
    FROM
      tb_user_video_log
    WHERE
      YEAR(end_time) = 2021
  )  t
  JOIN tb_video_info t2 ON t.video_id = t2.video_id
GROUP BY
  t.video_id
ORDER BY
  avg_comp_play_rate desc;
SELECT
  t.video_id ,
  ROUND(
    AVG(
      CASE
        WHEN TIMESTAMPDIFF(SECOND, t.start_time, t.end_time) >= duration THEN 1
        ELSE 0
      END
    ),
    3
  ) AS avg_comp_play_rate
FROM
  (
    SELECT *
    FROM
      tb_user_video_log
    WHERE
      YEAR(end_time) = 2021
  )  t
 inner JOIN tb_video_info t2 ON t.video_id = t2.video_id
GROUP BY
  t.video_id
ORDER BY
  avg_comp_play_rate desc;
select t1.video_id,round(ifnull(t2.c2/t1.c1,0),3) avg_comp_play_rate from 
(
    select video_id,count(*) c1 from tb_user_video_log 
    where year(start_time) = '2021' group by video_id
) t1
left join
(
    select a.video_id,count(*) c2 from tb_user_video_log a
    inner join tb_video_info b on a.video_id=b.video_id
    where timestampdiff(second,start_time,end_time) >= b.duration and year(start_time) = '2021'
    group by a.video_id
) t2
on t1.video_id = t2.video_id order by avg_comp_play_rate desc;

SQL157 平均播放进度大于60%的视频类别

计算各类视频的平均播放进度,将进度大于60%的类别输出。

-- 各类视频 的平均播放进度
select
  tag,
  concat(
    round(
      avg(
        if(
          timestampdiff(second, start_time, end_time) >= duration,
          duration,
          timestampdiff(second, start_time, end_time)
        ) / duration * 100
      ),
      2
    ),
    '%'
  ) as avg_play_progress
from
  tb_user_video_log u
  join tb_video_info v using(video_id)
group by
  tag -- 筛选进度大于60%
having
  replace(avg_play_progress, '%', '') > 60
order by
  avg_play_progress desc;
--时间相减用timestampdiff函数
--注意时间相减直接用减号有效性差容易出错,最好用函数,如timestampdif(天(DAY)、小时(HOUR),分钟(MINUTE)和秒(SECOND),早的时间点,晚的时间点)
SELECT
  CONCAT(
    ROUND(
      AVG(
        if(
          TIMESTAMPDIFF(SECOND, start_time, end_time) > duration,
          1,
          TIMESTAMPDIFF(SECOND, start_time, end_time) / duration
        )
      ) * 100,
      2
    ),
    '%'
  ) avg_rate
FROM
  tb_user_video_log a
  LEFT JOIN tb_video_info b on a.video_id = b.video_id
GROUP BY
  tag
HAVING
  REPLACE(avg_rate, '%', '') > 60

以上是关于数据库练习题(牛客网sql入门篇部分)的主要内容,如果未能解决你的问题,请参考以下文章

SQL日常练习2-进阶篇-牛客网

SQL日常练习1-基础篇-牛客网

SQL日常练习2-进阶篇-牛客网

牛客网专题SQL206 获取每个部门中当前员工薪水最高的相关信息

SQL练习题-牛客网

SQL练习题-牛客网