1667 修复表中的名字
select
user_id,
concat(upper(left(name,1)),lower(right(name,length(name)-1))) as name
from Users order by user_id;
concat()函数用法:用于将两个字符串连接成一个字符串
1484 按照日期分组销售产品
select sell_date,
count(distinct product) as num_sold,
group_concat(distinct product order by product separator ',')products
from Activities
group by sell_date
order by sell_date
group_concat()函数用法:数据类型表现为一对多,将“多”的一方进行连接
group_concat([DISTINCT] 要连接的字段 [Order BY ASC/DESC 排序字段] [Separator '分隔符'])
1527 患某种疾病的患者
select * from Patients where conditions regexp'\\bDIAB1'
regexp 正则表达式,注意\b 转义两次(\b 用法:用于匹配单词的开头/结尾)
1795 每个产品在不同商店的价格
select product_id,'store1' as store,store1 as price from Products
where store1 is not null
union all
select product_id,'store2' as store,store2 as price from Products
where store2 is not null
union all
select product_id,'store3' as store,store3 as price from Products
where store3 is not null
列转行(union all)
行转列(sum+if)
SQL 行转列,列转行_万物皆可休的博客-CSDN博客_sql行转列
197 上升的温度
# 计算比昨天高温的天数id
select w1.id from Weather w1,Weather w2
where datediff(w1.recordDate,w2.recordDate) = 1 and w1.Temperature > w2.Temperature
返回从特定日期到现在的天数:to_days("2022-07-20")
将时间/日期间隔添加到日期:adddate("2022-07-20",INTERVAL 1 day) # 2020-07-20
计算相差天数/小时数/秒数:
#计算相差天数:
select TIMESTAMPDIFF(DAY,'2019-05-20', '2019-05-21'); # 1
#计算相差小时数:
select TIMESTAMPDIFF(HOUR, '2015-03-22 07:00:00', '2015-03-22 18:00:00'); # 11
#计算相差秒数:
select TIMESTAMPDIFF(SECOND, '2015-03-22 07:00:00', '2015-03-22 7:01:01'); # 61
返回值是相差的天数:
DATEDIFF("2022-07-20","2022-07-21"); # 1
DATEDIFF("2022-07-22","2022-07-21"); # -1
从日期减去指定的时间间隔:DATE_SUB("2022-07-20",INTERVAL 2 DAY) # 2022-07-18
interval:"2022-07-21" + interval '1' day # 2022-07-22
177 第N高的薪水
这道题涉及到排序和排名,根据实际情况,排名的计数可以分成以下的情况:
① 同数不同排名:例如1000、2000、2000、4000排名为 1 2 3 4
② 同数不同排名且排名不连续:例如1000、2000、2000、4000排名为 1 2 2 4
③ 同数不同排名且排名连续:1例如1000、2000、2000、4000排名为 1 2 2 3
在mysql8.0以上可以采用内置函数:
① row_number(): 同数不同名,相当于行号,例如3000、2000、2000、1000排名后为1 2 3 4
② rank(): 同数不同排名且排名不连续,例如3000、2000、2000、1000排名后为1 2 2 4
③ dense_rank(): 同数不同排名且排名连续,例如3000、2000、2000、1000排名后为1 2 2 3
④ ntile(): 分桶排名,即首先按桶的个数分出第一二三桶,然后各桶内从1排名,实际不是很常用
另外这三个函数必须要要与其搭档over()配套使用,over()中的参数常见的有两个,分别是
partition by(按某字段切分);order by(与常规order by用法一致)也区分ASC(默认)和DESC,因为排名总得有个依据
注:下面代码仅在mysql8.0以上版本可用,最新OJ已支持。
over()函数:开窗函数,可以将数据分组查询之后再聚合
185 部门工资前三高的所有员工
前三高 = 不超过3个工资比这些值大
select Department.name as Department, Employee.name as Employee,Employee.salary as Salary
from Employee join Department on Employee.departmentId = Department.id
where 3 > (
select count(distinct e1.salary) from Employee e1
where e1.salary > Employee.salary and e1.departmentId = Employee.departmentId
)
# 筛选出e1中大于Employee的薪资且是同一个部门的薪资
184 部门工资最高的员工
自己写的:
select d.name as Department,e.name as Employee,e.salary as Salary
from Employee e join Department d on e.departmentId = d.id
where e.salary in(
select max(salary) from Employee
group by departmentId
)
正确答案:
select
d.Name as Department,
e.Name as Employee,
e.Salary
from
Employee e,Department d
where
e.DepartmentId=d.id
and
(e.Salary,e.DepartmentId) in (select max(Salary),DepartmentId from Employee group by DepartmentId);
知识补充:
左连接:left join 返回左表当中的全部行和右表与左表字段相等的行
右连接:right join 返回右表当中的全部行和左表与右表字段相等的行
内连接:inner join 返回两个表中连接字段相等的行(两表交集)
外连接:full join 左连接+右连接
笛卡尔积:cross join
自己写的报错是因为说:子查询出来的薪资,有可能是其他组的,应该带上组id
1407 排名靠前的旅行者
# 返回的结果表单,以 travelled_distance 降序排列
# 如果有两个或者更多的用户旅行了相同的距离, 那么再以 name 升序排列
SELECT u.name,IFNULL(SUM(r.distance),0) travelled_distance
FROM users u
LEFT JOIN rides r ON u.id = r.user_id
GROUP BY r.user_id
ORDER BY travelled_distance DESC, u.name ASC
知识点:
IFNULL(a,b) 函数:不为空则为a,为空则为b
left join和inner join
此处不能用inner join是因为会存在null的情况,而inner join会不保存null的情况的数据