当前位置: 首页 > news >正文

mysql-内置函数,复合查询和内外连接


一 日期函数
函数名称描述示例
current_date()返回当前日期(格式:yyyy-mm-dd)select current_date();2017-11-19
current_time()返回当前时间(格式:hh:mm:ss)select current_time();13:51:21
current_timestamp()返回当前日期和时间(格式:yyyy-mm-dd hh:mm:ss)select current_timestamp();2017-11-19 13:51:48
date(datetime)提取日期部分select date('2023-10-01 12:30:45');2023-10-01
date_add(date, interval n unit)日期加法(unit: year/day/minute/second)select date_add('2017-10-28', interval 10 day);2017-11-07
date_sub(date, interval n unit)日期减法(unit: year/day/minute/second)select date_sub('2017-10-01', interval 2 day);2017-09-29
datediff(date1, date2)计算两个日期间隔的天数(date1 - date2)select datediff('2017-10-10', '2016-09-01');404
now()返回当前日期和时间(同current_timestamp()insert into msg(content, sendtime) values('hello', now());

案例操作细节

  • 显示留言日期(不显示时间)
    select content, date(sendtime) from msg;  
    
  • 查询2分钟内发布的帖子
    select * from msg where date_add(sendtime, interval 2 minute) > now();  
    

二 字符串函数
函数名称描述示例
concat(str1, str2, ...)字符串拼接select concat(name, '的语文是', chinese, '分') from exam_result;
instr(str, substring)返回子串在字符串中的位置(从1开始,未找到返回0)select instr('hello', 'el');2
ucase(str) / lcase(str)转换为大写/小写select lcase(substring(ename, 1, 1)) from emp;
left(str, length)从左侧截取指定长度字符select left('abcdef', 3);abc
length(str)返回字符串字节长度(中文依赖字符集)select length('中文');6(utf8编码)
replace(str, old, new)替换字符串中的子串select replace(ename, 's', '上海') from emp;
substring(str, pos, len)从指定位置截取字符(pos从1开始,len可选)select substring(ename, 2, 2) from emp;
trim(str)去除字符串首尾空格select trim(' abc ');abc

案例操作细节

  • 显示姓名首字母小写
    select concat(lcase(substring(ename, 1, 1)), substring(ename, 2)) from emp;  
    
  • 计算字符串中逗号出现次数
    select length('10,a,b') - length(replace('10,a,b', ',', '')) as cnt;  
    

三 数学函数
函数名称描述示例
abs(num)绝对值select abs(-100.2);100.2
ceiling(num) / floor(num)向上取整 / 向下取整select ceiling(23.04);24floor(23.7);23
format(num, decimal_places)格式化数字(四舍五入保留小数位)select format(12.3456, 2);12.35
rand()生成[0.0, 1.0)的随机浮点数select rand();0.1234(随机值)
mod(num, denom)取模运算select mod(10, 3);1
conv(num, from_base, to_base)进制转换(如十进制转二进制)select bin(10);1010conv(10, 10, 2);1010

四 其他函数
函数名称描述示例
user()返回当前用户select user();root@localhost
database()返回当前使用的数据库select database();test_db
md5(str)计算md5哈希值(32位字符串)select md5('admin');21232f297a57a5a743894a0e4a801fc3
ifnull(val1, val2)若val1为null,返回val2;否则返回val1select ifnull(null, '123');123
password(str)对字符串加密(mysql用户密码专用)select password('root');*81f5e21e35407d884a6cd4a731ae8fb6...

关键操作细节
  1. 字符串长度计算

    • length()以字节为单位,中文在utf8中占3字节,gbk中占2字节。
    • 示例:select length('中文');6(utf8)。
  2. 日期范围查询

    • 使用date_add()date_sub()动态计算时间范围。
    • 示例:查询最近2分钟的数据:
      select * from msg where sendtime > date_sub(now(), interval 2 minute);  
      
  3. 空值处理

    • ifnull()用于替代null值,避免空指针问题。
    • 示例:select ifnull(qq, '未知') from students;
  4. 随机排序

    • 结合rand()order by实现随机抽取数据。
    • 示例:select * from exam_result order by rand() limit 1;

mysql复合查询


一、基本查询回顾
  • 条件过滤与排序

    -- 工资>500或岗位为manager,且姓名首字母大写  
    select * from emp where (sal>500 or job='manager') and ename like 'j%';  
    -- 按部门号升序、工资降序排序  
    select * from emp order by deptno, sal desc;  
    -- 按年薪降序排序  
    select ename, sal*12+ifnull(comm,0) as '年薪' from emp order by 年薪 desc;  
    
  • 子查询应用

    -- 显示工资最高的员工  
    select ename, job from emp where sal = (select max(sal) from emp);  
    -- 工资高于平均工资的员工  
    select ename, sal from emp where sal > (select avg(sal) from emp);  
    
  • 分组统计

    -- 每个部门的平均工资和最高工资  
    select deptno, format(avg(sal), 2), max(sal) from emp group by deptno;  
    -- 平均工资<2000的部门  
    select deptno, avg(sal) as avg_sal from emp group by deptno having avg_sal<2000;  
    -- 每种岗位的雇员总数和平均工资  
    select job, count(*), format(avg(sal),2) from emp group by job;  
    

二、多表查询
  • 联合查询(emp、dept、salgrade表)

    -- 显示员工名、工资、部门名(emp与dept关联)  
    select ename, sal, dname from emp, dept where emp.deptno = dept.deptno;  
    -- 显示部门10的部门名、员工名、工资  
    select ename, sal, dname from emp, dept where emp.deptno=dept.deptno and dept.deptno=10;  
    -- 显示员工工资等级(emp与salgrade关联)  
    select ename, sal, grade from emp, salgrade where sal between losal and hisal;  
    
  • 自连接(同一表内连接)

    -- 查询ford的上级领导(通过别名实现自连接)  
    select leader.empno, leader.ename from emp leader, emp worker   
    where leader.empno = worker.mgr and worker.ename='ford';  
    

三、子查询
  • 单行子查询(返回单行结果)

    -- 查询smith同部门的员工  
    select * from emp where deptno = (select deptno from emp where ename='smith');  
    
  • 多行子查询(返回多行结果)

    -- in: 查询与10号部门岗位相同的员工(不含10号部门)  
    select ename, job, sal, deptno from emp   
    where job in (select distinct job from emp where deptno=10) and deptno<>10;  
    -- all: 工资高于30号部门所有员工的员工  
    select ename, sal, deptno from emp where sal > all(select sal from emp where deptno=30);  
    -- any: 工资高于30号部门任意员工的员工  
    select ename, sal, deptno from emp where sal > any(select sal from emp where deptno=30);  
    
  • 多列子查询(返回多列结果)

    -- 查询与smith部门和岗位相同的员工(不含smith)  
    select ename from emp where (deptno, job)=(select deptno, job from emp where ename='smith') and ename<>'smith';  
    
  • from子句中的子查询(临时表)

    -- 显示工资高于部门平均工资的员工  
    select ename, deptno, sal, format(asal,2) from emp,  
    (select avg(sal) asal, deptno dt from emp group by deptno) tmp  
    where emp.sal > tmp.asal and emp.deptno=tmp.dt;  
    

四、合并查询
  • union(去重并集)

    -- 工资>2500或职位为manager的员工(去重)  
    select ename, sal, job from emp where sal>2500  
    union  
    select ename, sal, job from emp where job='manager';  
    
  • union all(不去重并集)

    -- 工资>2500或职位为manager的员工(保留重复)  
    select ename, sal, job from emp where sal>2500  
    union all  
    select ename, sal, job from emp where job='manager';  
    

五、实战操作
  • 查询员工入职时的薪水(按emp_no逆序)
    select emp_no, salary from salaries where from_date=hire_date order by emp_no desc;  
    
  • 生成所有表的count语句
    select concat('select count(*) from ', table_name, ';') from information_schema.tables where table_schema='当前数据库名';  
    
  • 获取非manager员工
    select emp_no from employees where emp_no not in (select emp_no from titles where title='manager');  
    

关键细节
  1. 多表连接必须指定条件,避免笛卡尔积(如emp.deptno = dept.deptno)。
  2. 自连接需使用别名区分表(如emp leader, emp worker)。
  3. 子查询在from中作为临时表,需定义别名并关联字段。
  4. union要求列数和类型一致,默认去重,union all保留重复。
  5. 聚合函数与group by配合,非聚合字段需包含在group by中。

mysql内外连接


一、内连接(inner join)

语法

select 字段 from1 inner join2 on 连接条件 [and 其他条件];  

特点

  • 仅返回两个表中匹配的行,不匹配的行被过滤。
  • 等价于使用where子句的隐式内连接(如select ... from 表1, 表2 where 表1.字段=表2.字段)。

案例

-- 显示smith的名字和部门名称  
-- 隐式内连接  
select ename, dname from emp, dept where emp.deptno=dept.deptno and ename='smith';  
-- 显式内连接  
select ename, dname from emp inner join dept on emp.deptno=dept.deptno and ename='smith';  

二、外连接(outer join)
1. 左外连接(left join)

语法

select 字段 from1 left join2 on 连接条件;  

特点

  • 左表(表1)完全显示,右表无匹配时填充null
  • 应用场景:需包含左表所有记录,即使右表无匹配。

案例

-- 学生表(stu)与成绩表(exam)左连接,显示所有学生(包括无成绩的)  
select * from stu left join exam on stu.id=exam.id;  

输出示例

+------+------+------+-------+  
| id   | name | id   | grade |  
+------+------+------+-------+  
| 1    | jack | 1    | 56    |  
| 2    | tom  | 2    | 76    |  
| 3    | kity | null | null  |  
| 4    | nono | null | null  |  
+------+------+------+-------+  
2. 右外连接(right join)

语法

select 字段 from1 right join2 on 连接条件;  

特点

  • 右表(表2)完全显示,左表无匹配时填充null
  • 应用场景:需包含右表所有记录,即使左表无匹配。

案例

-- 学生表(stu)与成绩表(exam)右连接,显示所有成绩(包括无学生的)  
select * from stu right join exam on stu.id=exam.id;  

输出示例

+------+------+------+-------+  
| id   | name | id   | grade |  
+------+------+------+-------+  
| 1    | jack | 1    | 56    |  
| 2    | tom  | 2    | 76    |  
| null | null | 11   | 8     |  
+------+------+------+-------+  

三、关键操作细节
  1. 连接条件必须明确

    • 使用on指定匹配条件(如stu.id=exam.id),避免笛卡尔积导致数据冗余。
  2. 外连接的优先级

    • 左外连接以左表为主,右外连接以右表为主。
    • 可通过调整表顺序实现相同效果:
      -- 方法1:左连接  
      select d.dname, e.* from dept d left join emp e on d.deptno=e.deptno;  
      -- 方法2:右连接  
      select d.dname, e.* from emp e right join dept d on d.deptno=e.deptno;  
      
  3. 过滤条件的放置

    • 若需对外连接结果进一步过滤,使用where而非on
      -- 显示左表中无匹配的部门  
      select d.dname from dept d left join emp e on d.deptno=e.deptno where e.empno is null;  
      

四、重难点总结
  • 区别内连接与外连接

    • 内连接:仅返回匹配行。
    • 外连接:保留主表所有行,辅表无匹配时填充null
  • 左连接 vs 右连接

    • 左连接以左表为主,右连接以右表为主。
    • 可通过调整表顺序互换使用。
  • 实际应用场景

    • 内连接:需精确匹配的场景(如员工与部门关联)。
    • 左/右外连接:需包含主表所有记录的场景(如显示所有学生成绩,即使无考试记录)。

五、实战应用
  • leetcode例题

    • rank-scores:使用自连接或窗口函数(需结合连接操作)。
    • exchange-seats:通过自连接或条件判断实现座位交换。
      内连接:仅返回匹配行。
    • 外连接:保留主表所有行,辅表无匹配时填充null
  • 左连接 vs 右连接

    • 左连接以左表为主,右连接以右表为主。
    • 可通过调整表顺序互换使用。
  • 实际应用场景

    • 内连接:需精确匹配的场景(如员工与部门关联)。
    • 左/右外连接:需包含主表所有记录的场景(如显示所有学生成绩,即使无考试记录)。

五、实战应用
  • leetcode例题
    • rank-scores:使用自连接或窗口函数(需结合连接操作)。
    • exchange-seats:通过自连接或条件判断实现座位交换。

相关文章:

  • 【React Hooks原理 - useCallback、useMemo】
  • 多语言笔记系列:Polyglot Notebooks 混合使用多语言并共享变量
  • 复刻低成本机械臂 SO-ARM100 标定篇
  • Vue常用优化
  • jeecg查询指定时间
  • 系统架构设计师:设计模式——行为设计模式
  • 【Touching China】2007-2011
  • WordPress不支持中文TAG标签出现404的解决方法
  • ES6入门---第三单元 模块三:async、await
  • LeetCode每日一题5.4
  • C++多态(上)
  • Java面试大纲(以及常见面试问答)
  • 如何查看电脑IP地址和归属地:全面指南
  • 强化学习机器人模拟器——RobotApp:一个交互式强化学习模拟器
  • Dify框架面试内容整理-Dify部署后常见问题有哪些?如何排查?
  • 【循环依赖(Circular Dependency)】
  • C++多态(下)
  • 自监督学习(Self-supervised Learning)李宏毅
  • 第十章.XML
  • langchain中 callbacks constructor实现
  • 江南华南较强降雨扰返程,北方大部需防风沙
  • 社区来电催生?多地回应:系为居民提供卫生健康服务
  • 新华每日电讯头版聚焦上海:科创高地向未来
  • 魔都眼|咖啡节上小孩儿忍不住尝了咖啡香,母亲乐了
  • 五一假期多地政府食堂对外开放:部分机关食堂饭菜“秒没”
  • 魔都眼|西岸国际咖啡生活节:连接艺术、音乐与宠物