SQL刷题记录
后天就考数据库概论了,今天继续练练力扣上的sql题目
以下皆出自力扣高频SQL50题

文章目录
25.12.21+22
2356
求每位老师教授科目种类数量
- 先按照老师分组
group by teacher_id - 再对count函数内的subject_id去重
DISTINCT的作用:在聚合函数内部,只考虑唯一值(去重)
sql
select teacher_id,count(distinct subject_id) as cnt from teacher group by teacher_id;
1045
sql
# 错误写法
select customer_id
from Customer c,Product p
group by c.customer_id
having count(c.product_key) = count(p.product_key);
FROM Customer c, Product p
→ 这是 隐式 CROSS JOIN(笛卡尔积),会把每个客户和每个产品都配对一次,运行没错但是结果出错
正确写法:
sql
# Write your MySQL query statement below
select customer_id
from Customer
group by customer_id
having count(product_key) = (select count(*) from Product);
COUNT(distinct product_key):客户买了多少不同的产品,记得要去重(SELECT COUNT(*) FROM Product):总共有多少产品
1731
sql
select e.employee_id,
e.name,
count(r.reports_to) as reports_count,
round(avg(r.age),0) as average_age
from Employees e
join Employees r
on e.employee_id = r.reports_to
group by r.reports_to
order by employee_id;
自连接
1978
sql
select
employee_id
from
Employees
where
salary<30000
and
manager_id is not null
and
manager_id not in(select employee_id from Employees)
order by
employee_id;
180
找出所有至少连续出现三次的数字
核心:
连续出现的意味着相同数字的 Id 是连着的,由于这题问的是至少连续出现 3 次
-
前三个的id是连续的,即
sqll1.id = l2.id -1 and l2.id = l3.id - 1 -
且前三个的num都一样
sqll1.num = l2.num and l2.num = l3.num
所以:
sql
select distinct l1.num as ConsecutiveNums
from Logs l1,Logs l2,Logs l3
where
l1.id = l2.id -1
and l2.id = l3.id - 1
and l1.num = l2.num
and l2.num = l3.num;
别忘了要去重
1667
- 分别截取首字母和剩余的字母
- 用upper函数把首字母转换成大写,用lower函数把剩余字母转换为小写
- 最后把两部分拼接起来
sql
select user_id,
concat(upper(left(name,1)),lower(substring(name,2)))
as name
from Users
order by user_id;
left也可换为substring(name,1,1)
MySQL常用的字符串操作函数
一、大小写转换
| 函数 | 说明 | 示例 |
|---|---|---|
UPPER(str) 或 UCASE(str) |
转大写 | UPPER('hello') → 'HELLO' |
LOWER(str) 或 LCASE(str) |
转小写 | LOWER('WORLD') → 'world' |
常用于统一格式、不区分大小写比较。
二、去除空格
| 函数 | 说明 | 示例 |
|---|---|---|
TRIM(str) |
去除首尾空格 | TRIM(' abc ') → 'abc' |
LTRIM(str) |
去除左侧空格 | LTRIM(' abc') → 'abc' |
RTRIM(str) |
去除右侧空格 | RTRIM('abc ') → 'abc' |
| `TRIM([LEADING | TRAILING | BOTH] 'x' FROM str)` |
三、截取子串
| 函数 | 说明 | 示例 |
|---|---|---|
SUBSTRING(str, pos, len) |
从位置 pos(从1开始)截取 len 个字符 |
SUBSTRING('abcdef', 2, 3) → 'bcd' |
SUBSTR(str, pos, len) |
同 SUBSTRING(别名) |
SUBSTR('hello', 1, 2) → 'he' |
LEFT(str, len) |
取左边 len 个字符 |
LEFT('hello', 2) → 'he' |
RIGHT(str, len) |
取右边 len 个字符 |
RIGHT('hello', 2) → 'lo' |
⚠️ 若
pos为负数,SUBSTRING从末尾开始(如SUBSTRING('abc', -2, 1) → 'b')。
四、查找位置
| 函数 | 说明 | 示例 |
|---|---|---|
LOCATE(substr, str [, start]) |
返回子串首次出现位置(从1开始),可指定起始位置 | LOCATE('o', 'hello') → 5 LOCATE('l', 'hello', 4) → 4 |
INSTR(str, substr) |
同 LOCATE,但参数顺序相反 |
INSTR('hello', 'l') → 3 |
POSITION(substr IN str) |
SQL 标准写法(MySQL 支持) | POSITION('ll' IN 'hello') → 3 |
未找到返回
0(不是 NULL)。
五、拼接字符串
| 函数 | 说明 | 示例 |
|---|---|---|
CONCAT(str1, str2, ...) |
拼接多个字符串 | CONCAT('a', 'b', 'c') → 'abc' |
CONCAT_WS(separator, str1, str2, ...) |
用分隔符拼接(自动跳过 NULL) | CONCAT_WS(',', 'a', NULL, 'c') → 'a,c' |
CONCAT()中任意参数为NULL,结果为NULL;CONCAT_WS会忽略NULL。
六、替换与填充
| 函数 | 说明 | 示例 |
|---|---|---|
REPLACE(str, from_str, to_str) |
替换所有匹配子串 | REPLACE('abcab', 'ab', 'X') → 'XcX' |
LPAD(str, len, padstr) |
左填充至 len 长度 |
LPAD('5', 3, '0') → '005' |
RPAD(str, len, padstr) |
右填充至 len 长度 |
RPAD('hi', 5, '*') → 'hi***' |
七、长度与重复
| 函数 | 说明 | 示例 |
|---|---|---|
LENGTH(str) |
返回字节数(注意:中文占多字节) | LENGTH('你好') → 6(UTF8) |
CHAR_LENGTH(str) |
返回字符数 | CHAR_LENGTH('你好') → 2 |
REPEAT(str, count) |
重复字符串 count 次 |
REPEAT('ha', 3) → 'hahaha' |
处理中文时,优先用
CHAR_LENGTH()获取字符个数。
八、其他实用函数
| 函数 | 说明 | 示例 |
|---|---|---|
REVERSE(str) |
反转字符串 | REVERSE('abc') → 'cba' |
INSERT(str, pos, len, newstr) |
从 pos 开始替换 len 个字符为 newstr |
INSERT('abcdef', 2, 3, 'XX') → 'aXXef' |
ELT(N, str1, str2, ...) |
返回第 N 个字符串(类似 switch) | ELT(2, 'a', 'b', 'c') → 'b' |
FIELD(str, str1, str2, ...) |
返回 str 在列表中的位置 |
FIELD('b', 'a', 'b', 'c') → 2 |
626
-
先用count求座位总数
-
若座位 id 是奇数的学生,修改其 id 为 id+1;如果最后一个座位 id 也是奇数,则最后一个座位 id 不修改;若座位 id 是偶数的学生,修改其 id 为 id-1
-
用case实现该功能
case的格式:
sqlCASE WHEN[val1]THEN[res1]...ELSE[default]END -- 如果val1为true,返回res1,...否则返回default -
最后用order by排序
sql
# Write your MySQL query statement below
select
(case
when id%2 != 0 and counts != id then id + 1
when id%2 != 0 and counts = id then id
else id - 1
end) as id,
student
from seat,(select count(*) as counts from seat) as seatCount
order by id;
记得给(select count(*) as counts from seat)起别名
因为每个派生表(子查询作为 FROM 的数据源)必须有一个别名(alias)
再优化一下
sql
SELECT
CASE
WHEN id % 2 = 1 AND id != (SELECT MAX(id) FROM Seat) THEN id + 1
WHEN id % 2 = 0 THEN id - 1
ELSE id
END AS id,
student
FROM Seat
ORDER BY id;
用max(id)直接得出id的数量
(最后刷几道简单题吧)
595
简单题,或者用or相连
sql
select name,population,area
from world
where area >= 3000000 or population >= 25000000;
1148
排序用order by
sql
select distinct author_id as id
from views
where author_id = viewer_id
order by id;
1683
MySQL中计算字符串字符个数的函数
| 函数 | 含义 | 返回值 | 适用场景 |
|---|---|---|---|
CHAR_LENGTH(str) |
字符个数 | 字符数量(按"字符"计) | 通用、安全,尤其含中文、emoji 等多字节字符时 |
LENGTH(str) |
字节数 | 字节长度(按"字节"计) | 仅当字符串全是单字节字符(如纯英文、数字、ASCII 符号)时 ≈ 字符数 |
sql
select
tweet_id
from
tweets
where
CHAR_LENGTH(content) > 15