SQL操作学习

牛客网在线编程_SQL篇_SQL快速入门

1.基础查询

去重关键字DISTINCT

需要从 user_profile 表中获取所有不同的大学名称

sql 复制代码
select distinct university 
from user_profile;
  • SELECT DISTINCT university: 选择 university 列,并去除重复的值。
  • FROM user_profile: 从 user_profile 表中获取数据。

查询结果限制返回行数

需要从 user_profile 表中选择 device_id 列,并只返回前两个用户的设备ID。

sql 复制代码
select device_id
from user_profile
limit 2;
  • LIMIT 子句用于限制查询结果的行数。
  • LIMIT 2: 限制返回的结果为前两行。

将查询后的列重新命名

user_profile 表中选择 device_id 列,并只返回前两个用户的设备ID,同时将结果列名更改为 user_infos_example

sql 复制代码
select device_id as user_infos_example
from user_profile
limit 2;
  • SELECT device_id AS user_infos_example: 选择 device_id 列,并将其重命名为 user_infos_example
  • FROM user_profile: 从 user_profile 表中获取数据。
  • LIMIT 2: 限制返回的结果为前两行。

2.条件查询

查找后排序

user_profile 表中选择 device_idage 列,并将结果按照 age 升序排列。

sql 复制代码
select device_id,age
from user_profile
order by age;
  • SELECT device_id, age: 选择 device_idage 列。
  • FROM user_profile: 从 user_profile 表中获取数据。
  • ORDER BY age ASC: 按照 age 升序排列结果。默认是升序

查找后多列排序

user_profile 表中选择 device_idagegpa 列,并将结果按照 gpa 升序排序,如果 gpa 相同,则再按照 age 升序排序。

sql 复制代码
select device_id,gpa,age
from user_profile
order by gpa,age;
  • SELECT device_id, gpa, age: 选择 device_idgpaage 列。
  • FROM user_profile: 从 user_profile 表中获取数据。
  • ORDER BY gpa ASC, age ASC: 先按照 gpa 升序排序,再按照 age 升序排序。

查找后降序排列

user_profile 表中选择 device_idgpaage 列,并将结果按照 gpa 降序排序,如果 gpa 相同,则再按照 age 降序排序。

sql 复制代码
select device_id,gpa,age
from user_profile
order by gpa desc,age desc;
  • SELECT device_id, gpa, age: 选择 device_idgpaage 列。
  • FROM user_profile: 从 user_profile 表中获取数据。
  • ORDER BY gpa DESC, age DESC: 先按照 gpa 降序排序,再按照 age 降序排序。

简单条件查找

sql 复制代码
select device_id,university
from user_profile
where university='北京大学';
sql 复制代码
select device_id,gender,age,university
from user_profile
where age>24;

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

sql 复制代码
select device_id,gender,age
from user_profile
where age between 20 and 23;

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

sql 复制代码
select device_id,gender,age,university
from user_profile
where university!='复旦大学';

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

sql 复制代码
select device_id,gender,age,university,gpa
from user_profile
where gender = 'male' and gpa>3.5;

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

sql 复制代码
select device_id,gender,age,university,gpa
from user_profile
where university='北京大学' or gpa>3.7;

找到gpa在3.5以上(不包括3.5)的山东大学用户 或 gpa在3.8以上(不包括3.8)的复旦大学同学进行用户调研,请你取出相应数据,取出的数据按照device_id升序排列

sql 复制代码
select device_id,gender,age,university,gpa
from user_profile
where (gpa > 3.5 and university = '山东大学')
or (gpa > 3.8 and university = '复旦大学')
order by device_id;

where过滤空值

user_profile 表中选择 device_idgenderageuniversity 列,并且只返回 age 不为空的记录。

sql 复制代码
select device_id,gender,age,university
from user_profile
where age is not NULL;
  • WHERE age IS NOT NULL: 只返回 age 不为空的记录。

Where in 和Not in

只返回 university 为"北京大学"、"复旦大学"或"山东大学"的记录。

sql 复制代码
select device_id,gender,age,university,gpa
from user_profile
where university in ('北京大学', '复旦大学', '山东大学');
  • WHERE university IN ('北京大学', '复旦大学', '山东大学'): 使用 IN 运算符筛选出满足任一条件的记录。

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

只返回 university 列中包含"北京"字样的记录。

sql 复制代码
select device_id,age,university
from user_profile
where university like '%北京%';

3.高级查询

查找GPA最高值

只返回 university 为"复旦大学"的记录中的最高 GPA 值

sql 复制代码
select format(gpa,1) as gpa
from user_profile
where university='复旦大学'
order by gpa desc
limit 1;
sql 复制代码
select format(max(gpa),1) as gpa
from user_profile
where university='复旦大学';
  • SELECT FORMAT(MAX(gpa), 1) AS gpa: 选择 gpa 的最大值,并使用 FORMAT() 函数将其格式化为小数点后1位。

计算男生人数以及平均GPA

user_profile 表中选择 gender 为"male"的记录,并计算这些记录的数量和 GPA 的平均值。

sql 复制代码
select count(*) as male_num,
format(avg(gpa),1) as avg_gpa
from user_profile
where gender = 'male';
  • SELECT COUNT(*) AS male_num: 计算 gender 为"male"的记录数量,并将结果命名为 male_num
  • ROUND(AVG(gpa), 1) AS avg_gpa: 计算 gpa 的平均值,并使用 ROUND() 函数保留到小数点后1位,结果命名为 avg_gpa
  • FROM user_profile: 从 user_profile 表中获取数据。
  • WHERE gender = 'male': 只返回 gender 为"male"的记录。

分组过滤

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

sql 复制代码
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(answer_cnt) < 20
    or avg(question_cnt) < 5;

选择_从什么表,按照学校分组,选择不用where语句而是having

分组排序练习题

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

sql 复制代码
select university,
       round(avg(question_cnt),4) as avg_question_cnt
from user_profile
group by university
order by avg(question_cnt);

多表查询

设有两张表:

A 表:user_profile

device_id university
2138 北京大学
2315 浙江大学
4321 复旦大学

B 表:question_practice_detail

device_id question_id result
2138 111 wrong
2315 115 right
2315 116 right
9999 120 wrong

我们通常按 device_id 连接。

1. 内连接 INNER JOIN(只保留两张表中能够匹配上的记录)

含义:只保留两张表中能够匹配上的记录。

sql 复制代码
SELECT *
FROM user_profile u
INNER JOIN question_practice_detail q
ON u.device_id = q.device_id;

结果只会保留:

  • 2138 能匹配

  • 2315 能匹配

4321 在答题表里没有,不要
9999 在用户表里没有,也不要

特点

内连接取的是两表的交集

考试里怎么理解

就是"有对应关系的才留下"。

2. 左外连接 LEFT JOIN(左表所有记录都保留,右表匹配不上就补 NULL

含义:以左表为主,左表所有记录都保留,右表匹配不上就补 NULL

sql 复制代码
SELECT *
FROM user_profile u
LEFT JOIN question_practice_detail q
ON u.device_id = q.device_id;

结果会保留 user_profile 的所有用户:

  • 2138 匹配上,显示题目数据

  • 2315 匹配上,显示题目数据

  • 4321 匹配不上,但这一行仍然保留,question_idresultNULL

特点

左连接取的是:

左表全部 + 右表中能匹配上的部分

适用场景

比如要查:

  • 所有用户及其答题情况

  • 即使没答题的用户也要显示出来

3. 右外连接 RIGHT JOIN(右表所有记录都保留,左表匹配不上就补 NULL)

含义:以右表为主,右表所有记录都保留,左表匹配不上就补 NULL

sql 复制代码
SELECT *
FROM user_profile u
RIGHT JOIN question_practice_detail q
ON u.device_id = q.device_id;

结果会保留 question_practice_detail 的所有答题记录:

  • 21382315 能匹配上

  • 9999 匹配不上用户信息,但仍会保留,用户表那边字段为 NULL

特点

右连接取的是:

右表全部 + 左表中能匹配上的部分

说明

实际开发里,右连接用得比左连接少。

因为把表顺序交换一下,很多右连接都能改写成左连接。

4. 全外连接 FULL OUTER JOIN(两边的记录都保留,匹配上的合并,匹配不上的补 NULL)

含义:两边的记录都保留,匹配上的合并,匹配不上的补 NULL

sql 复制代码
SELECT *
FROM user_profile u
FULL OUTER JOIN question_practice_detail q
ON u.device_id = q.device_id;

结果会保留:

  • 21382315 这种匹配上的

  • 4321 这种左边独有的

  • 9999 这种右边独有的

特点

全外连接取的是两表的并集

注意

有些数据库系统对 FULL OUTER JOIN 支持不好,比如 MySQL 早期版本不直接支持。

5. 交叉连接 CROSS JOIN(两张表做笛卡尔积)

含义:两张表做笛卡尔积。

sql 复制代码
SELECT *
FROM user_profile
CROSS JOIN question_practice_detail;

如果 A 表有 3 行,B 表有 4 行,结果就是 3 × 4 = 12 行。

特点

不需要连接条件,所有行两两配对。

适用场景

一般不常直接用,除非题目明确要求笛卡尔积,或者某些特殊组合场景。

危险点

如果忘了写连接条件,有时就会意外得到笛卡尔积,结果数量暴增。

子查询

浙江大学用户题目回答情况_牛客题霸_牛客网

sql 复制代码
SELECT u.device_id,q.question_id,q.result
from question_practice_detail q 
inner join user_profile u
where university = '浙江大学'and q.device_id=u.device_id
order by question_id;

链接查询

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

sql 复制代码
select u.university,
round(count(q.question_id)/ count(distinct(u.device_id)),4) as avg_answer_cnt

from user_profile u
inner join question_practice_detail q
on u.device_id = q.device_id
group by u.university;
# 该学校用户答题总次数除以答过题的不同用户个数

组合查询

现在运营想要分别查看学校为山东大学或者性别为男性的用户的device_id、gender、age和gpa数据,请取出相应结果,结果不去重。

(注意输出的顺序,先输出学校为山东大学再输出性别为男生的信息)

sql 复制代码
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';

case函数

sql 复制代码
CASE 测试表达式
WHEN 简单表达式1 THEN 结果表达式1
WHEN 简单表达式2 THEN 结果表达式2 ...
WHEN 简单表达式n THEN 结果表达式n
[ ELSE 结果表达式n+1 ]
END

题目:现在运营想要将用户划分为25岁以下和25岁及以上两个年龄段,分别查看这两个年龄段用户数量

本题注意:age为null 也记为 25岁以下

根据示例,你的查询应返回以下结果:

|---------|--------|
| age_cut | number |
| 25岁以下 | 4 |
| 25岁及以上 | 3 |

sql 复制代码
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;

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

sql 复制代码
select device_id,gender,
    case when age < 20 then '20岁以下'
         when age between 20 and 24 then '20-24岁'
         when age >= 25 then '25岁及以上'
         else '其他'
    end as age_cut
from user_profile;
相关推荐
一只大袋鼠2 小时前
数据库知识点梳理(二):从基础操作到底层原理
数据库·oracle
雷工笔记2 小时前
AI使用|通过AI学习物料分类编码表
笔记·学习
betazhou2 小时前
Oracle JDBC连接串解析DNS的改进
数据库·oracle
原来是猿2 小时前
MySQL【事务下】
数据库·mysql·oracle
2301_776508722 小时前
Python日志记录(Logging)最佳实践
jvm·数据库·python
东小黑3 小时前
WordPress问题
数据库·wordpress
2401_879693873 小时前
用Python批量处理Excel和CSV文件
jvm·数据库·python
gjc5923 小时前
踩坑实录:MySQL服务器CPU爆高,元凶竟是SELinux的setroubleshootd?
运维·服务器·数据库·mysql·adb
2401_846341653 小时前
Python Lambda(匿名函数):简洁之道
jvm·数据库·python