select ...
from ...
where ...
group by ...
having ...
order by ...
执行顺序:1.from 2.where 3.group by 4.having 5.select 6.order by
1.如果没带聚合函数不能再where条件后使用,可以在having和select处使用
2.正常group by后查询的字段就应该是group by的字段以及一些聚合的字段
3.没写group by默认一张表为一组
4.尽量用where,where无法实现再采取having
5.order by排序,默认升序,asc升序,desc降序(记忆方法a是小就是升,d是大就是降)
6.别名使用as ,as可以忽略,但是原字段和别名之间不应该有逗号,别名名字里有空格应该用引号括起来,当然实际上不应该出现这样的设计以及情况。
等于= 不等于<>,!= between…and…在什么之间操作符(左边应小于右边),is null 为空 ,and 且 , or 或(优先级小于=,注意括号问题),in(a,b相当与x='a’or x=‘b’) ,not(not like,is not null) ,like(模糊查询,没有%号相当于=,%在哪边就是哪边模糊,两边就是全模糊查询)
操作分组后的聚合函数需使用having,代码样例:
SELECT *,COUNT(*) AS num FROM emp
GROUP BY JOB,DEPTNO
HAVING num > 3
值得注意的是null值进行计算的时候会变为null,所以需要if null函数(字段,0)或者(字段,‘xxx’)
distinct只能出现在字段的最前方,但是可以被聚合函数包裹,去重规律为对后面的所有字段拼接按列拼接后不重复的记录,同时并不会处理Null值
count():算条数,count(*)不为空的行数,因为存在主键不为空,实际就是展示所有行记录,而count(字段)则是计算不为空的字段
sum():括号里填字段,对非空记录进行求和
avg():括号里填字段,对非空记录进行求平均数
max():括号里填字段,获取最大值
min():括号里填字段,获取最小值
1.需要从其他表获取值,联合展示即为连接查询
2.连接查询语法分类:
SQL92: 1992年出现的语法
缺点:结构不清晰,表连接条件,和后期进一步筛选的条件,糅杂在一起
SQL99: 1999年出现的语法
连接条件与筛选条件分离,即变为join … on … where的这种形式,比较清晰
3.连接方式
内连接:1.等值连接
2.非等值连接
3.自连接
外连接:
左外连接(左连接)
右外连接(右连接)
全连接
4.笛卡尔积
当两个表连接的时候没有进行条件约束,记录数会变成:行*行,所以要加约束条件避免增加表的连接次数
5.内连接
等值连接
SELECT
e.*,d.DNAME,d.LOC
FROM
emp e
JOIN
dept d
ON e.DEPTNO = d.DEPTNO
查薪资在什么级别范围,非等值连接
SELECT
e.ENAME,e.SAL,s.GRADE
from
emp e
JOIN
salgrade s
on e.SAL>s.LOSAL and e.SAL
自连接,查询员工以及其领导的名字(值得注意的是这种连接方式,如果没有等值是无法显示的比如没有上级领导)
SELECT
e.EMPNO,e.ENAME,e.MGR,em.ENAME as MRGNAME
FROM
emp e
JOIN
emp em
ON
e.MGR = em.EMPNO
6.外连接(left join以及right join)
SELECT
e.ENAME,d.DNAME
FROM
emp e
left JOIN
dept d
on e.DEPTNO = d.DEPTNO
SELECT
e.ENAME,d.DNAME
FROM
emp e
RIGHT JOIN
dept d
on e.DEPTNO = d.DEPTNO
区别在于有主次关系,哪边连接即哪边全表拼上另一边进行匹配
7.多表连接格式
select ... from a join b on a,b表条件 join c on 前面的表和c表的条件 join d on 前面的表和d表的条件
如查询员工的名字,部门名,薪资,薪资等级等
SELECT
e.ENAME,d.DNAME,s.GRADE
FROM
emp e
LEFT JOIN dept d ON e.DEPTNO = d.DEPTNO
LEFT JOIN salgrade s ON e.SAL BETWEEN s.LOSAL AND s.HISAL
全连接:FULL JOIN 即左右的空值都会并上去,一般不使用
8.子查询
什么是子查询
where条件子查询
案例:找出比最低工资高的员工姓名和工资
SELECT
e.ENAME,e.SAL
FROM emp e
WHERE e.SAL > (SELECT MIN(emp.SAL) as mini FROM emp)
from子句作为表的子查询
案例:找出每个岗位的平均工资(按岗位分组求平均值)
SELECT
t.*,s.GRADE
FROM
(SELECT JOB,AVG(SAL) AS salavg FROM emp GROUP BY JOB) t
JOIN salgrade s ON t.salavg BETWEEN s.LOSAL AND s.HISAL
上面的sql注意子表中的聚合函数需要其别名直接t.AVG(SAL)是不行的,不符合语法,因为会被认为函数,而聚合函数是后执行的
select后面的子查询
值得注意的是这里select子查询,返回的条件只能是一个字段以及一个值,为了不要出现错误可以使用limit)
SELECT
e.ENAME,(SELECT d.DNAME FROM dept d WHERE e.DEPTNO =d.DEPTNO LIMIT 1) as deptname FROM emp e
SELECT ENAME,JOB FROM emp WHERE JOB = 'MANAGER'
UNION
SELECT ENAME,JOB FROM emp WHERE JOB = 'SALESMAN'
虽然以上的语句可以使用or或者in实现,但是如果在表名字不一致情况下,就只能使用union,而且union的速度更快,在减少匹配的次数的情况下,还可以完成两个结果集的拼接。
比如:当 a连接b连接c
a 10条记录
b 10条记录
c 10条记录
匹配的次数是1000
a 连接 b 一个结果集: 10*10 -->100次
a 连接 c 一个结果集: 10*10 -->100次
使用union的话是:100次 + 100次 =200次 ====》乘法变成了加法
union要求在使用的时候要求上下的列数一致,在mysql对于列数据类型没要求,但是oracle的要求是需要一致的
1.limit使用
SELECT * FROM emp LIMIT 5
SELECT * FROM emp LIMIT 0,5
两个结果是一致的limit默认是startIndex,length,如果只有一个参数即去前面多少条的意思,startIndex是起始下标
SELECT * FROM emp LIMIT 3,5
上面即为实际的第4-9(4+5)的记录
2.通用分页
每页显示3条记录
第1页: limit 0,3 [0,1,2]
第2页: limit 3,3 [3,4,5]
第3页: limit 6,3 [6,7,8]
第4页: limit 9,3 [9,10,11]
根据上述规律得,每页显示pageSize 条记录
第pageNO页的记录公式为: limit((pageNO - 1) *pageSize ,pageSize )
当然有些前端或者后端的分页插件已经处理了-1这个事情所以编写代码的时候注意一下。
1.介绍
str_to_date:将字符串varchar转为date类型
date_format:将date类型转换成varchar类型
mysql的日期格式
%Y 年
%m 月
%d 日
%h 时
%i 分
%s 秒
2.示范语句
插入日期
INSERT INTO t_user(id,name,birth) VALUES ('1','zhangsan',STR_TO_DATE('1990-10-01','%Y-%m-%d'))
SELECT DATE_FORMAT(HIREDATE,'%Y-%m-%d') FROM emp
如果mysql的类型是date,如果传入的字符串是’1990-10-01’这种形式可以不使用str_to_date也可以。实际上mysql的date存储默认就是讲date转为’1990-10-01’(’%Y-%m-%d’)这种形式字符串存储
3.datetime
date是短日期,年月日,默认格式 %Y-%m-%d
datetime是长日期,年月日时分秒 %Y-%m-%d %h:%i:%s(中间的空格数不影响)
CREATE TABLE t_user(
id int,
name VARCHAR(32),
birth date,
create_time datetime
)
INSERT INTO t_user(id,name,birth,create_time) VALUES ('2','zhangsan','2020-10-01','2020-10-01 10:10:05')
使用日期的默认字符串形式插入即可
4.时间函数
now()函数,创建的当前时间带有时分秒信息,是datetime类型的
约束包括哪些?
1.非空约束:not null
2.唯一性约束:unique
3.主键约束:primary key(简称pk)
4.外键约束:foreign key(简称fk)
5.检查约束:cherk(mysql不支持,oracle支持)
1.在字段后面写not null即为非空约束(列级别约束)
2.唯一unique可以加在字段后面,也可以加在创建语句语句最后独立行unique(‘name’,‘phone’)联合主键 (列级别,表级别约束都可,具体看是否是联合)
3.not null 和unique可联合使用,这样写会默认变成主键约束,mysql中是,Oracle不是
4.primary key可以是列级别的,也可以是表级别的即联合主键primary key(id,name)
即为复合主键,一张表的主键约束只能是一个要不就列级别,要不就复合。
(1)主键值建议int,bigint等数字类型类型
不建议使用varchar来做主键,一般都用数字类型,且定长
(2)设计中:有自然主键和业务主键
自然主键:是一个自然数,和业务没关系
业务主键:主键值和业务紧密关联,例如拿银行卡账号做主键值,这就是业务主键
(3)mysql有自带自增机制:auto_increament
5.外键约束(foreign key,简称fk)
外键约束即给本表的某个字段添加约束,使其的值只能等于关联表的值,即存在主次关系,或者说父子关系,被约束即被加外键的为子,其实数据需遵循父的数据,所有需要先创建父即参考表。创建表以及插入顺序也是先父,再子。
写法: foregin key(字段) references table(字段)
还可以给外键加别名,主表的字段是必须unique级别以上,不一定是主键
(1)在Mysql中取消外键约束: SET FOREIGN_KEY_CHECKS=0;
(2)然后再设置外键约束: SET FOREIGN_KEY_CHECKS=1;
默认存储引擎是InnoDB
默认的编码是:utf8,实际中最好使用utf8mb4
source 路径斜杠文件名.sql
/*
Navicat Premium Data Transfer
Source Server : localhost
Source Server Type : MySQL
Source Server Version : 50729
Source Host : localhost:3306
Source Schema : sqltest
Target Server Type : MySQL
Target Server Version : 50729
File Encoding : 65001
Date: 18/07/2021 17:14:44
*/
SET NAMES utf8mb4;
SET FOREIGN_KEY_CHECKS = 0;
-- ----------------------------
-- Table structure for dept
-- ----------------------------
DROP TABLE IF EXISTS `dept`;
CREATE TABLE `dept` (
`DEPTNO` int(2) NOT NULL COMMENT '部门编号',
`DNAME` varchar(14) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '部门名称',
`LOC` varchar(13) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '地区',
PRIMARY KEY (`DEPTNO`) USING BTREE
) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci ROW_FORMAT = Dynamic;
-- ----------------------------
-- Records of dept
-- ----------------------------
INSERT INTO `dept` VALUES (10, 'ACCOUNTING', 'NEW YORK');
INSERT INTO `dept` VALUES (20, 'RESEARCH', 'DALLAS');
INSERT INTO `dept` VALUES (30, 'SALES', 'CHICAGO');
INSERT INTO `dept` VALUES (40, 'OPERATIONS', 'BOSTON');
-- ----------------------------
-- Table structure for emp
-- ----------------------------
DROP TABLE IF EXISTS `emp`;
CREATE TABLE `emp` (
`EMPNO` int(4) NOT NULL COMMENT '员工编号',
`ENAME` varchar(10) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '员工名',
`JOB` varchar(9) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '岗位',
`MGR` int(4) NULL DEFAULT NULL COMMENT '领导编号',
`HIREDATE` date NULL DEFAULT NULL COMMENT '聘用日期',
`SAL` double(7, 2) NULL DEFAULT NULL COMMENT '薪资',
`COMM` double(7, 2) NULL DEFAULT NULL COMMENT '津贴',
`DEPTNO` int(2) NULL DEFAULT NULL COMMENT '部门编号',
PRIMARY KEY (`EMPNO`) USING BTREE
) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci ROW_FORMAT = Dynamic;
-- ----------------------------
-- Records of emp
-- ----------------------------
INSERT INTO `emp` VALUES (7369, 'SMITH', 'CLERK', 7902, '1980-12-17', 800.00, NULL, 20);
INSERT INTO `emp` VALUES (7499, 'ALLEN', 'SALESMAN', 7698, '1981-02-20', 1600.00, 300.00, 30);
INSERT INTO `emp` VALUES (7521, 'WARD', 'SALESMAN', 7698, '1981-02-22', 1250.00, 500.00, 30);
INSERT INTO `emp` VALUES (7566, 'JONES', 'MANAGER', 7839, '1981-04-02', 2975.00, NULL, 20);
INSERT INTO `emp` VALUES (7654, 'MARTIN', 'SALESMAN', 7698, '1981-09-28', 1250.00, 1400.00, 30);
INSERT INTO `emp` VALUES (7698, 'BLAKE', 'MANAGER', 7839, '1981-05-01', 2850.00, NULL, 30);
INSERT INTO `emp` VALUES (7782, 'CLARK', 'MANAGER', 7839, '1981-06-09', 2450.00, NULL, 10);
INSERT INTO `emp` VALUES (7788, 'SCOTT', 'ANALYST', 7566, '1987-04-19', 3000.00, NULL, 20);
INSERT INTO `emp` VALUES (7839, 'KING', 'PRESIDENT', NULL, '1981-11-17', 5000.00, NULL, 10);
INSERT INTO `emp` VALUES (7844, 'TURNER', 'SALESMAN', 7698, '1981-09-08', 1500.00, 0.00, 30);
INSERT INTO `emp` VALUES (7876, 'ADAMS', 'CLERK', 7788, '1987-05-23', 1100.00, NULL, 20);
INSERT INTO `emp` VALUES (7900, 'JAMES', 'CLERK', 7698, '1981-12-03', 950.00, NULL, 30);
INSERT INTO `emp` VALUES (7902, 'FORD', 'ANALYST', 7566, '1981-12-03', 3000.00, NULL, 20);
INSERT INTO `emp` VALUES (7934, 'MILLER', 'CLERK', 7782, '1982-01-23', 1300.00, NULL, 10);
-- ----------------------------
-- Table structure for salgrade
-- ----------------------------
DROP TABLE IF EXISTS `salgrade`;
CREATE TABLE `salgrade` (
`GRADE` int(11) NOT NULL COMMENT '级别',
`LOSAL` int(11) NULL DEFAULT NULL COMMENT '最低薪资',
`HISAL` int(11) NULL DEFAULT NULL COMMENT '最高薪资'
) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci ROW_FORMAT = Dynamic;
-- ----------------------------
-- Records of salgrade
-- ----------------------------
INSERT INTO `salgrade` VALUES (1, 700, 1200);
INSERT INTO `salgrade` VALUES (2, 1201, 1400);
INSERT INTO `salgrade` VALUES (3, 1401, 2000);
INSERT INTO `salgrade` VALUES (4, 2001, 3000);
INSERT INTO `salgrade` VALUES (5, 3001, 9999);
-- ----------------------------
-- Table structure for t_user
-- ----------------------------
DROP TABLE IF EXISTS `t_user`;
CREATE TABLE `t_user` (
`id` int(11) NULL DEFAULT NULL,
`name` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL,
`birth` date NULL DEFAULT NULL,
`create_time` datetime(0) NULL DEFAULT NULL
) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci ROW_FORMAT = Dynamic;
-- ----------------------------
-- Records of t_user
-- ----------------------------
INSERT INTO `t_user` VALUES (1, 'zhangsan', '2020-10-01', '2020-10-01 10:10:05');
INSERT INTO `t_user` VALUES (2, 'zhangsan', '2020-10-01', '2020-10-01 10:10:05');
INSERT INTO `t_user` VALUES (3, 'zhangsan', '2020-10-01', '2021-07-17 22:19:39');
SET FOREIGN_KEY_CHECKS = 1;