从MySQL到ORM(二):MySQL基础
一、基本概念
1.数据库:
数据库(DataBase)就是一个存储数据的仓库,为了方便数据的存储和管理,它将数据按照特定的规律存储在磁盘上。通过数据库管理系统,可以有效的组织和管理存储在数据库中的数据。数据库是数据管理软件。数据存储分为三个阶段:人工管理阶段、文件系统阶段和数据库系统阶段。
2.数据库范式:
数据库范式即数据库应该遵循的规则。目前关系数据库最常用的四种范式分别是:第一范式(1NF)、第二范式(2NF)、第三范式(3NF)、BCN范式(BCNF)。
第一范式:无重复的域。即数据库表的每一列都是不可分割的原子数据项,而不是集合、数组、记录等非原子数据项。
第二范式:数据库表中的所有列都必须依赖于主键,这意味着一个表只描述一件事情。
第三范式:表中的每一列只与主键直接相关而不是间接相关。
BCN范式:Boyce-Codd,不允许出现有主键的一部分被主键另一部分或者其他部分决定。即一个表中只能有一个主键。
举例(摘自其他博客)说明BCN:
假设仓库管理关系表为StorehouseManage(仓库ID, 存储物品ID, 管理员ID, 数量),且有一个管理员只在一个仓库工作;一个仓库可以存储多种物品。这个数据库表中存在如下决定关系:
(仓库ID, 存储物品ID) →(管理员ID, 数量)
(管理员ID, 存储物品ID) → (仓库ID, 数量)
所以,(仓库ID, 存储物品ID)和(管理员ID, 存储物品ID)都是StorehouseManage的候选关键字,表中的唯一非关键字段为数量,它是符合第三范式的。但是,由于存在如下决定关系:
(仓库ID) → (管理员ID)
(管理员ID) → (仓库ID)
即存在关键字段决定关键字段的情况,所以其不符合BCNF范式。
3.数据库系统和数据库管理系统:
数据库系统由数据库、数据库管理系统、应用开发工具构成。
数据库管理系统(DataBase Management System, DBMS)是用来定义、管理和维护数据的软件。它是数据库系统的重要组成部分。数据库管理系统通过SQL语言来管理数据库中的数据。
4.SQL语言:
SQL(Structured Query Language)语言的全称是结构化查询语言。它包括:
- 数据库定义语言(Data Definition Language, DDL)
- 数据操作语言(Data Manipulation Language, DML)
- 数据控制语言(Data Control Language, DCL)
5.MySQL数据库版本和优势:
常见数据库
商业数据库:甲骨文的Oracle、IBM的DB2、微软的Access和SQL Server。开源数据库:PostgreSQL、MySQL。
版本分类
根据操作系统:Windows版,UNIX版,Linux版,MacOS版;根据开发情况:Alpha、Beta、Gamma与Available(GA)。
alpha 暗示这是一个以展示新特性为目的的版本,存在比较多的不稳定因素,还会向代码中添加新新特性
beta 以后的beta版、发布版或产品发布中,所有API、外部可视结构和SQL命令列均不再更改,不再向代码中添加影响代码稳定性的新特性。Gamma比Beta版更高级。
GA如果没有后缀,则暗示这是一个大多数情况下可用版本或者是产品版本。. GA releases则是稳定版。
优势:MySQL开放源码、跨平台性、价格优势、功能强大且使用方便。
Linux安装MySQL
https://www.cnblogs.com/kuaizifeng/p/8884842.html
二、MySQL数据类型(摘自菜鸟教程:http://www.runoob.com/mysql/mysql-data-types.html)
MySQL支持多种类型,大致可以分为三类:数值、日期/时间和字符串(字符)类型。
1.整数类型的存储和范围
类型 | 大小 | 范围(有符号) | 范围(无符号) | 用途 |
---|---|---|---|---|
TINYINT | 1 字节 | (-128,127) | (0,255) | 小整数值 |
SMALLINT | 2 字节 | (-32 768,32 767) | (0,65 535) | 大整数值 |
MEDIUMINT | 3 字节 | (-8 388 608,8 388 607) | (0,16 777 215) | 大整数值 |
INT或INTEGER | 4 字节 | (-2 147 483 648,2 147 483 647) | (0,4 294 967 295) | 大整数值 |
BIGINT | 8 字节 | (-9 233 372 036 854 775 808,9 223 372 036 854 775 807) | (0,18 446 744 073 709 551 615) | 极大整数值 |
FLOAT | 4 字节 | (-3.402 823 466 E+38,-1.175 494 351 E-38),0,(1.175 494 351 E-38,3.402 823 466 351 E+38) | 0,(1.175 494 351 E-38,3.402 823 466 E+38) | 单精度 浮点数值 |
DOUBLE | 8 字节 | (-1.797 693 134 862 315 7 E+308,-2.225 073 858 507 201 4 E-308),0,(2.225 073 858 507 201 4 E-308,1.797 693 134 862 315 7 E+308) | 0,(2.225 073 858 507 201 4 E-308,1.797 693 134 862 315 7 E+308) | 双精度 浮点数值 |
DECIMAL | 对DECIMAL(M,D) ,如果M>D,为M+2否则为D+2 | 依赖于M和D的值 | 依赖于M和D的值 | 小数值 |
2.日期和时间类型
类型 | 大小 | 范围 | 格式 | 用途 |
---|---|---|---|---|
DATE | 3 | 1000-01-01/9999-12-31 | YYYY-MM-DD | 日期值 |
TIME | 3 | '-838:59:59'/'838:59:59' | HH:MM:SS | 时间值或持续时间 |
YEAR | 1 | 1901/2155 | YYYY | 年份值 |
DATETIME | 8 | 1000-01-01 00:00:00/9999-12-31 23:59:59 | YYYY-MM-DD HH:MM:SS | 混合日期和时间值 |
TIMESTAMP | 4 |
1970-01-01 00:00:00/2038 结束时间是第 2147483647 秒,北京时间 2038-1-19 11:14:07,格林尼治时间 2038年1月19日 凌晨 03:14:07 |
YYYYMMDD HHMMSS | 混合日期和时间值,时间戳 |
3.字符串类型
类型 | 大小 | 用途 |
---|---|---|
CHAR | 0-255字节 | 定长字符串 |
VARCHAR | 0-65535 字节 | 变长字符串 |
TINYTEXT | 0-255字节 | 短文本字符串 |
TEXT | 0-65 535字节 | 长文本数据 |
MEDIUMTEXT | 0-16 777 215字节 | 中等长度文本数据 |
LONGTEXT | 0-4 294 967 295字节 | 极大文本数据 |
TINYBLOB | 0-255字节 | 不超过 255 个字符的二进制字符串 |
BLOB | 0-65 535字节 | 二进制形式的长文本数据 |
MEDIUMBLOB | 0-16 777 215字节 | 二进制形式的中等长度文本数据 |
LONGBLOB | 0-4 294 967 295字节 | 二进制形式的极大文本数据 |
三、MySQL表操作
1.插入数据 INSERT INTO
-- 插入一条新的数据 /* INSERT INTO customers(cust_id, cust_name, cust_address, cust_city, cust_state, cust_zip, cust_country, cust_contact, cust_email) VALUES('10006', 'Toy Land', '123 Any Street', 'New York', 'NY', '11111', 'USA', NULL, NULL); */ -- 按表列字段的顺序插入数据时,列字段可省略 INSERT INTO customers VALUES('10006', 'Toy Land', '123 Any Street', 'New York', 'NY', '11111', 'USA', NULL, NULL); -- 将一张表插入到原来的表 /* INSERT INTO customers(cust_id, cust_name, cust_address, cust_city, cust_state, cust_zip, cust_country, cust_contact, cust_email) SELECT cust_id, cust_name, cust_address, cust_city, cust_state, cust_zip, cust_country, cust_contact, cust_email FROM cust_new WHERE cust_id NOT IN (SELECT cust_id FROM customers); */ -- 复制表 CREATE TABLE custcopy AS SELECT * FROM customers;
注意:
- 任何SELECT选项和子句都可以使用,包括WHERE和GROUP BY。
- 可以联结多个表执行插入数据操作。
- 不管从多少个表中检索数据,数据都只能插入到单个表中。
2.更新和删除数据 UPDARE DEL
UPDATE可以:更新表中特定行,更新表中所有行。在没有where子句时,UPDATE会更新所有记录。
-- UPDATE总以要更新的表的名字开始,以SET指明一个或多个要更新的字段,以WHERE指定要更新的记录 UPDATE customers SET cust_email = 'kim@thetoystore.com' WHERE cust_id = '10005'; UPDATE customers SET cust_contact = 'Sam Roberts', cust_email = 'sam@toyloand.com' WHERE cust_id = '10006'; -- 设置NULL来删除某个列的值 UPDATE customers SET cust_email = NULL WHERE cust_id = '10005';
-- DELETE是删除列 DELETE FROM customers WHERE cust_id = '10006';
DELETE用于按行删除记录,它本身不会修改表结构。
注:在对UPDATE或DELETE语句使用WHERE子句前,应该先用SELECT进行测试,以保证它过滤的是确实要删除的记录。
3.创建表及约束条件
1.创建表
-- 创建表语法:CREATE TABLE [IF NOT EXISTS] table_name(column_name data_type,...); CREATE TABLE users(id SMALLINT UNSIGNED PRIMARY KEY AUTO_INCREMENT, name VARCHAR(20), salary FLOAT(8,2) UNSIGNED); -- 查看表结构 DESC users; SHOW COLUMNS FROM users; SHOW CREATE TABLE users;
2.约束条件
约束是为了保证数据的完整性和一致性,约束类型包括:
键名 | 类型 |
PRIMARY KEY | 主键约束 |
UNIQUE KEY | 唯一约束 |
NOT NULL | 非空约束 |
UNSIGNED | 无符号约束 |
DEFAULT | 默认约束 |
FOREIGN KEY | 外键约束 |
4.修改表结构
1.添加和删除列
-- 修改数据表 -- 添加列语法: ALTER TABLE tbl_name ADD [COLUMN] col_name column_definition [FIRST|AFTER col_name] ALTER TABLE users ADD age TINYINT UNSIGNED NOT NULL DEFAULT 10 AFTER name; -- 删除列语法: ALTER TABLE tbl_name DROP [COLUMN] col_name ALTER TABLE users DROP age; -- 混合操作 ALTER TABLE users ADD gender VARCHAR(10) NOT NULL DEFAULT "male", ADD address VARCHAR(32) NOT NULL,DROP salary;
2.修改列定义和列名
-- 修改列名,要重新声明列的数据类型和约束条件 ALTER TABLE users CHANGE name username varchar(10) NOT NULL; -- 修改列定义 ALTER TABLE users MODIFY id SMALLINT NOT NULL FIRST; -- 修改表名 ALTER TABLE users RENAME TO tb;
四、MySQL查询操作
1、查询数据
1.查询关键字 SELECT FROM
-- 查询单列 SELECT prod_name FROM products; -- 查询多列 SELECT prod_id, prod_name, prod_price FROM products; -- 查询所有列 SELECT * FROM products;
2.排序关键字 ORDER BY
查询的数据如果不排序,一般是以它在底层表中出现的顺序显示。如果不明确规定排序顺序,则不应该假定检索出的数据的顺序有意义。
-- 单排 SELECT prod_name FROM products ORDER BY prod_name; -- 多排 SELECT prod_id, prod_price, prod_name FROM products ORDER BY prod_price, prod_name; -- 按列位置排 SELECT prod_id, prod_price, prod_name FROM products ORDER BY 2, 3; 注,它只能根据已选择字段的相对位置排序 -- 指定排序方向 SELECT prod_id, prod_price, prod_name FROM products ORDER BY prod_price DESC, prod_name;
3.过滤关键字 where + 操作符
where子句操作符表:
操作符 | 说明 |
= | 等于 |
<> | 不等于 |
!= | 不等于 |
< | 小于 |
<= | 小于等于 |
!< | 不小于 |
> | 大于 |
>= | 大于等于 |
!> | 不大于 |
BETWEEN | 在指定的两个值之间 |
IS NULL | 为null值 |
AND、OR、NOT、IN | 组合查询 |
LIKE | 通配符过滤 |
用例:
-- 匹配查询 SELECT prod_price, prod_name FROM products where prod_price = 3.49; -- 不匹配查询 SELECT prod_price, prod_name FROM products where prod_price <> 10; -- 范围查询 SELECT prod_price, prod_name FROM products where prod_price BETWEEN 5 AND 10; -- 空值查询 SELECT prod_name FROM products where prod_price IS NULL; -- 组合查询AND SELECT prod_id, prod_name, prod_price FROM products WHERE vend_id='DLL01' AND prod_price <= 4; -- 组合查询OR SELECT prod_name, prod_price FROM products WHERE vend_id='DLL01' OR vend_id = 'BRS01'; -- 组合查询AND和OR SELECT prod_name, prod_price FROM products WHERE vend_id='DLL01' OR vend_id = 'BRS01' AND prod_price <= 4; -- 组合查询IN SELECT prod_name, prod_price FROM products WHERE vend_id IN ('DLL01', 'BRS01') ORDER BY prod_name; -- 组合查询NOT SELECT prod_name, prod_price FROM products WHERE vend_id NOT vend_id='DLL01'; -- 通配符过滤 SELECT prod_name FROM products WHERE prod_name LIKE '%TNT%';
2、数据处理函数
1.文本处理函数
函数 | 说明 |
LEFT | 返回字符串左边的字符 |
LENGTH | 返回字符串的长度 |
LOWER | 返回字符串的小写 |
LTRIM | 去掉字符串左边的空格 |
RIGHT | 返回字符串右边的字符 |
RTRIM | 去掉字符串右边的空格 |
UPPER | 返回字符串的大写 |
- 用例:
SELECT vend_name, UPPER(vend_name) AS vend_name_upcase FROM vendors ORDER BY vend_name;
2.日期和时间处理函数
注:日期和时间函数根据https://blog.****.net/qinshijangshan/article/details/72874667整理
函数 | 说明 |
NOW()、SYSDATE()、CURRENT_TIMESTAMP、LOCALTIME、LOCALTIMESTAMP | 获取当前日期和时间 |
CURDATE(), CURRENT_DATE | 获取当前日期 |
CURTIME(), CURRENT_TIME | 获取当前时间 |
DATE、YEAR、QUARTER、MONTH、WEEK、DAY、HOUR、MINUTE、SECOND、MICROSECOND | 获取指定日期和时间的日期、年、季度、月、周、日、小时、分钟、秒、毫秒数 |
WEEKOFYEAR、DAYOFYEAR、DAYOFMONTH、DAYOFWEEK、LAST_DAY | 获取指定日期和时间的年周索引、年天索引、月天索引、周天索引,最后一天的日期 |
MONTHNAME、 DAYNAME | 获取指定日期和时间的英文月名、英文天名 |
DATE_ADD、DATE_SUB | 指定日期按指定参数进行加减运算 |
PERIOD_ADD、PERIOD_DIFF | 指定日期加、减多少个月 |
TIMEDIFF | 指定日期和时间相差多少个时间 |
TIMESTAMPDIFF | 指定日期/时间或日期时间的差值 |
TO_DAYS、FROM_DAYS | 日期和月数的相互转换函数 |
TIME_TO_SEC、SEC_TO_TIME | 时间和秒数的相互转换函数 |
STR_TO_DATE、DATE_FORMAT | 字符串/日期时间格式转换成新的格式 |
TIME_FORMAT | 时间格式转换你成新的格式 |
MAKEDATE、MAKETIME | 拼凑日期/时间 |
UNIX_TIMESTAMP、FROM_UNIXTIME | 日期时间和unix时间戳的相互转化 |
用例:
-- 获取当前日期和时间,日期指的是年月日,时间指的是时分秒 SELECT NOW(), SYSDATE(), CURRENT_TIMESTAMP, LOCALTIME, LOCALTIMESTAMP; -- 分别获取当前日期和时间 SELECT CURDATE(), CURRENT_DATE, CURTIME(), CURRENT_TIME; -- 分别获取日期时间、年、季度、月、周、日、时、分、秒 SELECT DATE(SYSDATE()), YEAR(SYSDATE()), QUARTER(SYSDATE()), MONTH(SYSDATE()), WEEK(SYSDATE()), DAY(SYSDATE()), HOUR(SYSDATE()), MINUTE(SYSDATE()), SECOND(SYSDATE()), MICROSECOND(SYSDATE()); -- 获取指定索引 SELECT WEEKOFYEAR(SYSDATE()), DAYOFYEAR(SYSDATE()), DAYOFMONTH(SYSDATE()), DAYOFWEEK(SYSDATE()), LAST_DAY(SYSDATE()); -- 获取月和周的英文名称 SELECT MONTHNAME(SYSDATE()), DAYNAME(SYSDATE());
-- DATE加,第一个参数是指定的日期和时间,第二个参数是间隔和单位 SELECT DATE_ADD(now(), INTERVAL 1 YEAR), DATE_ADD(now(), INTERVAL 2 MONTH), DATE_ADD(now(), INTERVAL 1000 SECOND); -- DATE减,与DATE加参数相同 SELECT DATE_SUB(now(), INTERVAL 1 YEAR), DATE_SUB(now(), INTERVAL 2 MONTH), DATE_SUB(now(), INTERVAL 1000 SECOND); -- 日期的加减运算 SELECT PERIOD_ADD(201808, 2), PERIOD_ADD(1808, 2),PERIOD_ADD(DATE_FORMAT(SYSDATE(), '%Y%m'), 2), PERIOD_DIFF(201808, 201004), PERIOD_DIFF(1808, 1004); -- 时间差计算 SELECT TIMEDIFF('2018-08-06', '2018-08-5');-- 不支持日期 SELECT TIMEDIFF('19:00:00', '17:00:00'), TIMEDIFF('2018-08-6 9:30:30', '2018-08-5 17:00:00'); -- 更便捷的日期/时间差值计算,第一个参数是要计算的字段,其值为第三个日期时间减去第二个日期时间 SELECT TIMESTAMPDIFF(DAY, '2018-08-5 17:00:00', '2018-08-8 9:30:30'), TIMESTAMPDIFF(DAY, '2018-08-5', '2018-08-8'); SELECT TIMESTAMPDIFF(SECOND, '17:00:00', '19:30:30');-- 不支持单独时间计算 -- 日期和天数的相互转换 SELECT TO_DAYS(SYSDATE()), TO_DAYS('2018-8-8'), FROM_DAYS(737279); -- 时间和秒数的相互转换 SELECT TIME_TO_SEC(SYSDATE()), TIME_TO_SEC('12:00:00'), SEC_TO_TIME(43200); -- 字符串格式化;字符串格式化成日期只能要按照字符串的写法改写成标准日期时间字符串 SELECT STR_TO_DATE('2018.08.6 9:30:30', '%Y.%m.%d %H:%i:%s'); -- 日期时间字符串可以随便更改或获取字段 SELECT DATE_FORMAT('2018-08-06 09:30:30', '%Y%m');-- 获取年月的组合字符串 SELECT DATE_FORMAT('2018-08-06 09:30:30', '%H%i%s');-- 获取时分秒的组合字符串 SELECT DATE_FORMAT(SYSDATE(), '%Y年%m月%d日 %H时哈哈%i分嘿嘿%d秒呵呵');-- 重新格式化 -- 时间格式化只能格式化时间 SELECT TIME_FORMAT('2018-08-06 09:30:30', '%Y年%m月%d日 %H时%i分%d秒'); -- 只对'09:30:30'进行格式化,日期全部为00 SELECT TIME_FORMAT('09:30:30', '%H时%i分%d秒'); -- MAKEDATE根据数字组合成日期(以天数换算),MAKETIME根据数字组合成时间 SELECT MAKEDATE(2018, 9);-- 结果是'2018-01-09'而不是'2018-09-01' SELECT MAKEDATE(2018, 220);-- 结果是'2018-08-08' SELECT MAKETIME(19,30,30);-- 与日期相反,支持三个参数拼接而不支持两个参数换算 -- 日期时间和unix时间的相互转换 SELECT UNIX_TIMESTAMP(), FROM_UNIXTIME(UNIX_TIMESTAMP());
3.数值处理函数
函数 | 说明 |
ABS() | 返回数字表达式的绝对值。 |
ACOS() | 返回数字表达式的反余弦值。如果值是不在范围-1到1,则返回NULL。 |
ASIN() | 返回数字表达式的反正弦。返回NULL,如果值不在范围-1到1 |
ATAN() | 返回数字表达式的反正切。 |
ATAN2() | 返回传递给它的两个变量的反正切。 |
BIT_AND() | 返回按位AND运算表达中的所有位。 |
BIT_COUNT() | 返回传递给它的二进制值的字符串表示。 |
BIT_OR() | 返回传递表达的所有位的位或。 |
CEIL() | 返回最小的整数值但不能比传递的数字表达式小 |
CEILING() | 返回最小的整数值但不能比传递的数字表达式小 |
CONV() | 表达式从一个基数到另一个基数转换的数字。 |
COS() | 返回传递数字表达式的余弦值。数字表达式应该用弧度表示。 |
COT() | 返回传递数字表达式的余切。 |
DEGREES() | 返回数字表达式从弧度转换为度。 |
EXP() | 返回数值表达式的自然对数(E)为基数的幂。 |
FLOOR() | 返回最大整数值但不能大于通过表达式数值。 |
FORMAT() | 返回数字表达式舍入到小数位数。 |
GREATEST() | 返回输入表达式的最大值。 |
INTERVAL() | 需要多个表达式exp1, exp2和exp3等..如果为exp1小于exp2返回0,如果为exp1小于exp3返回1等。 |
LEAST() | 给两个或两个以上时,返回所有输入的最小值。 |
LOG() | 返回通过数字表达式的自然对数。 |
LOG10() | 返回传递表达的基数为10对数的数值。 |
MOD() | 返回表达式由另一个表达式除以剩余部分。 |
OCT() | 返回通过数字表达式的八进制值的字符串表示。如果传递值为NULL,返回NULL。 |
PI() | 返回圆周率的值 |
POW() | 返回一个表达式到另一个表达的次方值 |
POWER() | 返回一个表达式到另一个表达的次方值 |
RADIANS() | 返回传递表达从度转换为弧度值 |
ROUND() | 返回数字表达式四舍五入到整数。可用于舍入表达式为小数点数值 |
SIN() | 返回给定的数字表达的正弦值(弧度) |
SQRT() | 返回数字表达式的非负平方根 |
STD() | 返回数字表达式的标准偏差 |
STDDEV() | 返回数字表达式的标准偏差 |
TAN() | 返回以弧度表示数值表达式的正切值。 |
TRUNCATE() | 返回exp1小数位数字截断到exp2。如果exp2为0,则结果将没有小数点。 |
4.聚合函数
函数 | 说明 |
AVG | 返回某列的平均值 |
COUNT | 返回某类的行数 |
MAX | 返回某列的最大值 |
MIN | 返回某列的最小值 |
SUM | 返回某列值之和 |
用例:
-- AVG SELECT AVG(prod_price) AS avg_price FROM products; SELECT AVG(prod_price) AS avg_price FROM products WHERE vend_id=1003; SELECT AVG(DISTINCT prod_price) AS avg_price FROM products WHERE vend_id=1003;-- 计算唯一值列表平均值 -- COUNT SELECT COUNT(*) AS num_cust FROM customers;-- 对所有行技数 SELECT COUNT(cust_email) as num_cust FROM customers;-- 只对具有电子邮寄地址的客户计数(除去null) -- SUM SELECT SUM(item_price * quantity) AS total_price FROM orderitems WHERE order_num = 20005; -- 组合 SELECT COUNT(*) AS nun_items, MIN(prod_price) AS price_min, MAX(prod_price) AS pric_max, AVG(prod_price) AS price_ag FROM products;
3、分组关键字 GROUP BY 和HAVING
1.GROUP BY
- GROUP BY子句可以包含任意数目的列。
- GROUP BY会在最后规定的分组上进行汇总。
- GROUP BY子句列出的每个列都必须是检索列或有效的表达式(但不能是聚合函数)。
- 除聚合函数外,SELECT语句中的每个列都必须在GROUP BY子句中给出。
- 如果分组列中具有NULL值,则NULL将作为一个分组返回;如果列中有多行NULL值,它们将分为一组。
- GROUP BY子句必须出现在WHERE子句字后,ORDER BY子句之前。
一般在使用GROUP BY子句时,应该也给出ORDER BY子句,以保证数据正确排序。
2.HAVING
HAVING支持所有WHERE操作符。它与WHERE最重要的区别是,HAVING对GROUP BY分组后的数据进行过滤,而where在GROUP BY分组前组织新表时进行过滤。
用例:
-- GROUP BY 与 HAVINNG SELECT cust_id, COUNT(*) AS orders FROM orders GROUP BY cust_id HAVING COUNT(*) >= 2; -- GROUP BY 与 ORDER BY SELECT order_num, COUNT(*) AS items FROM orderitems GROUP BY order_num HAVING COUNT(*) >= 3 ORDER BY items, order_num;
4、关键字顺序
关键字(子句) | 说明 |
是否必须使用 |
SELECT | 要返回的列或表达式 | 是 |
FROM | 从中检索数据的表 | 仅在从表选择数据时使用 |
WHERE | 行级过滤 | 否 |
GROUP BY | 分组说明 | 仅在按组计算聚集时使用 |
HAVING | 组级过滤 | 否 |
ORDER BY | 指定排序字段和熟顺序 | 否 |
在实现SQL语句时,通用格式为:
SELECT *columns* FROM *tables* WHERE *condition* GROUP BY *columns* HAVING *condition* ORDER BY *columns* LIMIT *start*, *offset*;
实际执行的顺序为:
FROM *tables* WHERE *condition* GROUP BY *columns* HAVING *condition* SELECT *columns* ORDER BY *columns* LIMIT *start*, *offset*
# 注:数据表来自https://www.cnblogs.com/sanjun/p/8274469.html。
CREATE TABLE customers ( cust_id int NOT NULL AUTO_INCREMENT, cust_name char(50) NOT NULL , cust_address char(50) NULL , cust_city char(50) NULL , cust_state char(5) NULL , cust_zip char(10) NULL , cust_country char(50) NULL , cust_contact char(50) NULL , cust_email char(255) NULL , PRIMARY KEY (cust_id) ) ENGINE=InnoDB; CREATE TABLE orderitems ( order_num int NOT NULL , order_item int NOT NULL , prod_id char(10) NOT NULL , quantity int NOT NULL , item_price decimal(8,2) NOT NULL , PRIMARY KEY (order_num, order_item) ) ENGINE=InnoDB; CREATE TABLE orders ( order_num int NOT NULL AUTO_INCREMENT, order_date datetime NOT NULL , cust_id int NOT NULL , PRIMARY KEY (order_num) ) ENGINE=InnoDB; CREATE TABLE products ( prod_id char(10) NOT NULL, vend_id int NOT NULL , prod_name char(255) NOT NULL , prod_price decimal(8,2) NOT NULL , prod_desc text NULL , PRIMARY KEY(prod_id) ) ENGINE=InnoDB; CREATE TABLE vendors ( vend_id int NOT NULL AUTO_INCREMENT, vend_name char(50) NOT NULL , vend_address char(50) NULL , vend_city char(50) NULL , vend_state char(5) NULL , vend_zip char(10) NULL , vend_country char(50) NULL , PRIMARY KEY (vend_id) ) ENGINE=InnoDB; CREATE TABLE productnotes ( note_id int NOT NULL AUTO_INCREMENT, prod_id char(10) NOT NULL, note_date datetime NOT NULL, note_text text NULL , PRIMARY KEY(note_id), FULLTEXT(note_text) ) ENGINE=MyISAM; ALTER TABLE orderitems ADD CONSTRAINT fk_orderitems_orders FOREIGN KEY (order_num) REFERENCES orders (order_num); ALTER TABLE orderitems ADD CONSTRAINT fk_orderitems_products FOREIGN KEY (prod_id) REFERENCES products (prod_id); ALTER TABLE orders ADD CONSTRAINT fk_orders_customers FOREIGN KEY (cust_id) REFERENCES customers (cust_id); ALTER TABLE products ADD CONSTRAINT fk_products_vendors FOREIGN KEY (vend_id) REFERENCES vendors (vend_id); INSERT INTO customers(cust_id, cust_name, cust_address, cust_city, cust_state, cust_zip, cust_country, cust_contact, cust_email) VALUES(10001, 'Coyote Inc.', '200 Maple Lane', 'Detroit', 'MI', '44444', 'USA', 'Y Lee', 'ylee@coyote.com'); INSERT INTO customers(cust_id, cust_name, cust_address, cust_city, cust_state, cust_zip, cust_country, cust_contact) VALUES(10002, 'Mouse House', '333 Fromage Lane', 'Columbus', 'OH', '43333', 'USA', 'Jerry Mouse'); INSERT INTO customers(cust_id, cust_name, cust_address, cust_city, cust_state, cust_zip, cust_country, cust_contact, cust_email) VALUES(10003, 'Wascals', '1 Sunny Place', 'Muncie', 'IN', '42222', 'USA', 'Jim Jones', 'rabbit@wascally.com'); INSERT INTO customers(cust_id, cust_name, cust_address, cust_city, cust_state, cust_zip, cust_country, cust_contact, cust_email) VALUES(10004, 'Yosemite Place', '829 Riverside Drive', 'Phoenix', 'AZ', '88888', 'USA', 'Y Sam', 'sam@yosemite.com'); INSERT INTO customers(cust_id, cust_name, cust_address, cust_city, cust_state, cust_zip, cust_country, cust_contact) VALUES(10005, 'E Fudd', '4545 53rd Street', 'Chicago', 'IL', '54545', 'USA', 'E Fudd'); INSERT INTO vendors(vend_id, vend_name, vend_address, vend_city, vend_state, vend_zip, vend_country) VALUES(1001,'Anvils R Us','123 Main Street','Southfield','MI','48075', 'USA'); INSERT INTO vendors(vend_id, vend_name, vend_address, vend_city, vend_state, vend_zip, vend_country) VALUES(1002,'LT Supplies','500 Park Street','Anytown','OH','44333', 'USA'); INSERT INTO vendors(vend_id, vend_name, vend_address, vend_city, vend_state, vend_zip, vend_country) VALUES(1003,'ACME','555 High Street','Los Angeles','CA','90046', 'USA'); INSERT INTO vendors(vend_id, vend_name, vend_address, vend_city, vend_state, vend_zip, vend_country) VALUES(1004,'Furball Inc.','1000 5th Avenue','New York','NY','11111', 'USA'); INSERT INTO vendors(vend_id, vend_name, vend_address, vend_city, vend_state, vend_zip, vend_country) VALUES(1005,'Jet Set','42 Galaxy Road','London', NULL,'N16 6PS', 'England'); INSERT INTO vendors(vend_id, vend_name, vend_address, vend_city, vend_state, vend_zip, vend_country) VALUES(1006,'Jouets Et Ours','1 Rue Amusement','Paris', NULL,'45678', 'France'); INSERT INTO products(prod_id, vend_id, prod_name, prod_price, prod_desc) VALUES('ANV01', 1001, '.5 ton anvil', 5.99, '.5 ton anvil, black, complete with handy hook'); INSERT INTO products(prod_id, vend_id, prod_name, prod_price, prod_desc) VALUES('ANV02', 1001, '1 ton anvil', 9.99, '1 ton anvil, black, complete with handy hook and carrying case'); INSERT INTO products(prod_id, vend_id, prod_name, prod_price, prod_desc) VALUES('ANV03', 1001, '2 ton anvil', 14.99, '2 ton anvil, black, complete with handy hook and carrying case'); INSERT INTO products(prod_id, vend_id, prod_name, prod_price, prod_desc) VALUES('OL1', 1002, 'Oil can', 8.99, 'Oil can, red'); INSERT INTO products(prod_id, vend_id, prod_name, prod_price, prod_desc) VALUES('FU1', 1002, 'Fuses', 3.42, '1 dozen, extra long'); INSERT INTO products(prod_id, vend_id, prod_name, prod_price, prod_desc) VALUES('SLING', 1003, 'Sling', 4.49, 'Sling, one size fits all'); INSERT INTO products(prod_id, vend_id, prod_name, prod_price, prod_desc) VALUES('TNT1', 1003, 'TNT (1 stick)', 2.50, 'TNT, red, single stick'); INSERT INTO products(prod_id, vend_id, prod_name, prod_price, prod_desc) VALUES('TNT2', 1003, 'TNT (5 sticks)', 10, 'TNT, red, pack of 10 sticks'); INSERT INTO products(prod_id, vend_id, prod_name, prod_price, prod_desc) VALUES('FB', 1003, 'Bird seed', 10, 'Large bag (suitable for road runners)'); INSERT INTO products(prod_id, vend_id, prod_name, prod_price, prod_desc) VALUES('FC', 1003, 'Carrots', 2.50, 'Carrots (rabbit hunting season only)'); INSERT INTO products(prod_id, vend_id, prod_name, prod_price, prod_desc) VALUES('SAFE', 1003, 'Safe', 50, 'Safe with combination lock'); INSERT INTO products(prod_id, vend_id, prod_name, prod_price, prod_desc) VALUES('DTNTR', 1003, 'Detonator', 13, 'Detonator (plunger powered), fuses not included'); INSERT INTO products(prod_id, vend_id, prod_name, prod_price, prod_desc) VALUES('JP1000', 1005, 'JetPack 1000', 35, 'JetPack 1000, intended for single use'); INSERT INTO products(prod_id, vend_id, prod_name, prod_price, prod_desc) VALUES('JP2000', 1005, 'JetPack 2000', 55, 'JetPack 2000, multi-use'); INSERT INTO orders(order_num, order_date, cust_id) VALUES(20005, '2005-09-01', 10001); INSERT INTO orders(order_num, order_date, cust_id) VALUES(20006, '2005-09-12', 10003); INSERT INTO orders(order_num, order_date, cust_id) VALUES(20007, '2005-09-30', 10004); INSERT INTO orders(order_num, order_date, cust_id) VALUES(20008, '2005-10-03', 10005); INSERT INTO orders(order_num, order_date, cust_id) VALUES(20009, '2005-10-08', 10001); INSERT INTO orderitems(order_num, order_item, prod_id, quantity, item_price) VALUES(20005, 1, 'ANV01', 10, 5.99); INSERT INTO orderitems(order_num, order_item, prod_id, quantity, item_price) VALUES(20005, 2, 'ANV02', 3, 9.99); INSERT INTO orderitems(order_num, order_item, prod_id, quantity, item_price) VALUES(20005, 3, 'TNT2', 5, 10); INSERT INTO orderitems(order_num, order_item, prod_id, quantity, item_price) VALUES(20005, 4, 'FB', 1, 10); INSERT INTO orderitems(order_num, order_item, prod_id, quantity, item_price) VALUES(20006, 1, 'JP2000', 1, 55); INSERT INTO orderitems(order_num, order_item, prod_id, quantity, item_price) VALUES(20007, 1, 'TNT2', 100, 10); INSERT INTO orderitems(order_num, order_item, prod_id, quantity, item_price) VALUES(20008, 1, 'FC', 50, 2.50); INSERT INTO orderitems(order_num, order_item, prod_id, quantity, item_price) VALUES(20009, 1, 'FB', 1, 10); INSERT INTO orderitems(order_num, order_item, prod_id, quantity, item_price) VALUES(20009, 2, 'OL1', 1, 8.99); INSERT INTO orderitems(order_num, order_item, prod_id, quantity, item_price) VALUES(20009, 3, 'SLING', 1, 4.49); INSERT INTO orderitems(order_num, order_item, prod_id, quantity, item_price) VALUES(20009, 4, 'ANV03', 1, 14.99); INSERT INTO productnotes(note_id, prod_id, note_date, note_text) VALUES(101, 'TNT2', '2005-08-17', 'Customer complaint: Sticks not individually wrapped, too easy to mistakenly detonate all at once. Recommend individual wrapping.' ); INSERT INTO productnotes(note_id, prod_id, note_date, note_text) VALUES(102, 'OL1', '2005-08-18', 'Can shipped full, refills not available. Need to order new can if refill needed.' ); INSERT INTO productnotes(note_id, prod_id, note_date, note_text) VALUES(103, 'SAFE', '2005-08-18', 'Safe is combination locked, combination not provided with safe. This is rarely a problem as safes are typically blown up or dropped by customers.' ); INSERT INTO productnotes(note_id, prod_id, note_date, note_text) VALUES(104, 'FC', '2005-08-19', 'Quantity varies, sold by the sack load. All guaranteed to be bright and orange, and suitable for use as rabbit bait.' ); INSERT INTO productnotes(note_id, prod_id, note_date, note_text) VALUES(105, 'TNT2', '2005-08-20', 'Included fuses are short and have been known to detonate too quickly for some customers. Longer fuses are available (item FU1) and should be recommended.' ); INSERT INTO productnotes(note_id, prod_id, note_date, note_text) VALUES(106, 'TNT2', '2005-08-22', 'Matches not included, recommend purchase of matches or detonator (item DTNTR).' ); INSERT INTO productnotes(note_id, prod_id, note_date, note_text) VALUES(107, 'SAFE', '2005-08-23', 'Please note that no returns will be accepted if safe opened using explosives.' ); INSERT INTO productnotes(note_id, prod_id, note_date, note_text) VALUES(108, 'ANV01', '2005-08-25', 'Multiple customer returns, anvils failing to drop fast enough or falling backwards on purchaser. Recommend that customer considers using heavier anvils.' ); INSERT INTO productnotes(note_id, prod_id, note_date, note_text) VALUES(109, 'ANV03', '2005-09-01', 'Item is extremely heavy. Designed for dropping, not recommended for use with slings, ropes, pulleys, or tightropes.' ); INSERT INTO productnotes(note_id, prod_id, note_date, note_text) VALUES(110, 'FC', '2005-09-01', 'Customer complaint: rabbit has been able to detect trap, food apparently less effective now.' ); INSERT INTO productnotes(note_id, prod_id, note_date, note_text) VALUES(111, 'SLING', '2005-09-02', 'Shipped unassembled, requires common tools (including oversized hammer).' ); INSERT INTO productnotes(note_id, prod_id, note_date, note_text) VALUES(112, 'SAFE', '2005-09-02', 'Customer complaint: Circular hole in safe floor can apparently be easily cut with handsaw.' ); INSERT INTO productnotes(note_id, prod_id, note_date, note_text) VALUES(113, 'ANV01', '2005-09-05', 'Customer complaint: Not heavy enough to generate flying stars around head of victim. If being purchased for dropping, recommend ANV02 or ANV03 instead.' ); INSERT INTO productnotes(note_id, prod_id, note_date, note_text) VALUES(114, 'SAFE', '2005-09-07', 'Call from individual trapped in safe plummeting to the ground, suggests an escape hatch be added. Comment forwarded to vendor.' );
推荐阅读
-
从入门到精通 MYsql的数据库学习使用心得_MySQL
-
将数据库从 MySQL 移植到 MemSQL
-
Linux下将数据库从MySQL迁移到MariaDB的基础操作教程
-
从mysql导出数据到mongodb数据库 博客分类: 文档存储nosql MongoDBMySQLjsonWordPressCSS
-
从MySQL到MongoDB简易对照表 博客分类: 文档存储nosql MySQLMongoDB数据结构SQL
-
Spring boot开发从Excel表格导入大数据量(十万级/百万级)数据到数据库(MySQL)的工具
-
datax从mysql同步数据到elasticsearch(使用es的动态模板)
-
MySQL 从入门到跑路_01(实例实操)
-
MySQL从入门到跑路_02 (实例实操)
-
Mysql从删库到跑路