里面不少理论解释都是复制《MYSQL必知必会》
目录
里面不少理论解释都是复制《MYSQL必知必会》
第四章 检索数据
第五章 排序检索数据
第六章 过滤数据
第7章 数据过滤
第8章 利用通配符进行过滤
使用通配符的技巧
第九章 正则表达式
第十章创建计算字段
第十一章 使用数据处理函数
sql的函数分为:
文本处理函数
日期处理函数
数值处理函数
第十二章 汇总数据
第十三章 分组数据
第十四章 使用子查询
第四章 检索数据
知识点 select语句使用 DISTINCT去重,limit返回限定行数
-- --检索单个列
select prod.prod_name from products prod;
-- 检索多个列
select prod.prod_id,prod.prod_name,prod.prod_price,prod.prod_desc from products prod;
-- 检索所有列
SELECT * FROM products ;
-- 利用DISTINCT关键字去除重复数据
SELECT DISTINCT p.vend_id from products p;
-- 注意! 不能部分的使用DISTINCT,你加了两个列名上去,除非两个列都不同,否则所有行都会被检索出来
-- 限制结果 使用Limit子句
select prod_name from products LIMIT 5;
-- 此语句使用select检索出单个列,limit 5 指示mysql返回不多于5行的数据
select prod_name from products LIMIT 5,5;
-- 这个limit语句表示mysql返回从第5行开始的5行数据,第一个数为开始的位置,第二个数为要检索的行树。
-- 所以:带1个值的limit总是从第一行开始,给出的数为返回的行数。带两个值的limit可以指定从行号为第一个值的位置开始。
第五章 排序检索数据
知识点 ORDER BY排序,排序结合limit找出第几大物品的值
-- 使用orderBy对数据进行排序 指示以prod_name为排序依据,将以字母顺序排序数据
SELECT * FROM products p ORDER BY p.prod_name;
-- 按多个列进行排序,假设排序人名,如果姓重了,可以根据名再进行排序。
-- 在这里则是按照价格和名称进行排序,优先排序价格,价格相同则根据名称排序
SELECT * FROM products p ORDER BY p.prod_price, p.prod_name;
-- 可以对排序的方向进行指定,例如升序ASC(A-Z),或者降序DESC(Z-A)
-- 对价格进行降序排序,相同则根据名称进行升序排序
SELECT * FROM products p ORDER BY p.prod_price DESC, p.prod_name ;
-- 使用ORDER BY和limit可以找出一个列中最高或最低的值
-- 找出最昂贵物品的信息
select * from products p ORDER BY prod_price DESC LIMIT 1;
第六章 过滤数据
where操作符
本章知识点: select语句利用where子句过滤返回数据,where子句的操作符。null值检测。
-- 使用where子句
-- where可以根据特定条件来返回符合条件的数据
-- 返回价格为2.50的行
SELECT * FROM products p where p.prod_price = 2.50;
-- 在同时使用ORDER BY的时候,必须让ORDER BY放在where后面
SELECT * FROM products p where p.prod_price > 2.50 ORDER BY p.prod_price;
-- 错误用法
-- SELECT * FROM products p ORDER BY p.prod_price where p.prod_price > 2.50;
-- 检查单个值
SELECT * FROM products p where p.prod_name = 'fuses';
SELECT * FROM products p where p.prod_price <= 10;
-- 不匹配检查
SELECT * FROM products p where vend_id <> 1003;
SELECT * FROM products p where vend_id != 1003;
-- 两种写法是等价的
-- 范围值检查 BETWEEN
-- BETWEEN可以用来检查某个范围的值 用法为 Where xxx BETWEEN x and x
-- 可以用来检索价格或者时间日期
SELECT * FROM products p where p.prod_price BETWEEN 5 and 10;
-- 空值检查
-- 检查email为空的
SELECT * FROM customers c where c.cust_email is null;
-- 检查email不为空的
SELECT * FROM customers c where c.cust_email is not null;
第7章 数据过滤
知识点:AND和OR关键字来组成where子句
计算次序,以及如何管理计算的次序
IN操作符及其优点:
为什么要使用 IN 操作符?其优点具体如下。
在使用长的合法选项清单时, IN 操作符的语法更清楚且更直观。
在使用 IN 时,计算的次序更容易管理(因为使用的操作符更少)。
IN 操作符一般比 OR 操作符清单执行更快。
IN 的最大优点是可以包含其他 SELECT 语句,使得能够更动态地建
立 WHERE 子句。第 14 章将对此进行详细介绍。
NOT操作符
-- 为了进行更强的过滤控制,可以使用多个where字句。利用AND或者OR子句的方式来使用
-- 找出供应商ID为1003【且】价格小于等于10的数据
-- AND会联结条件,并指示DBMS只返回满足给定条件的行
select * from products p where p.vend_id = 1003 and p.prod_price <= 10;
-- OR操作符告诉DBMS匹配任一条件而不是同时匹配两个条件。如果使用了AND这里会没有数据返回
-- OR指示MYSQL检索匹配任一满足条件的行
select * from products p where p.vend_id = 1003 OR p.prod_price <= 5;
-- 计算次序
-- where可包含任意数目的AND和OR操作符。允许两者结合以进行复杂和高级的过滤
-- 但是AND和OR带来了一个问题,即操作符的优先级问题
SELECT vend_id,prod_name, prod_price FROM products WHERE vend_id = 1002 OR vend_id = 1003 AND prod_price >= 10;
-- 请看上面的结果。返回的行中有两行价格小于10美元,显然,
-- 返回的行未按预期的进行过滤。为什么会这样呢?原因在于计
-- 算的次序。SQL(像多数语言一样)在处理OR操作符前,优先处理AND操
-- 作符。当SQL看到上述WHERE子句时,它理解为由供应商1003制造的任何
-- 价格为10美元(含)以上的产品,或者由供应商1002制造的任何产品,
-- 而不管其价格如何。换句话说,由于AND在计算次序中优先级更高,操作
-- 符被错误地组合了。
-- 解决的方法就是使用括号明确分组相应的操作。
SELECT vend_id,prod_name, prod_price FROM products WHERE (vend_id = 1002 OR vend_id = 1003) AND prod_price >= 10;
-- 这条SELECT语句与前一条的唯一差别是,这条语句中,前两个条件用圆括号括了起来。因为圆括号具有较AND或OR操作符高的计算次序,
-- DBMS首先过滤圆括号内的OR条件。这时,SQL语句变成了选择由供应商1002或1003制造的且价格都在10美元(含)以上的任何产品,
-- 这正是我们所希望的。
-- IN操作符
-- IN操作符用来指定条件范围,范围中的每个条件都可以进行匹配。
select * from products p where p.vend_id in(1002,1003);
-- 能用in代替or的话最好用in
-- 为什么要使用IN操作符?其优点具体如下。
-- 1.在使用长的合法选项清单时,IN操作符的语法更清楚且更直观。
-- 2.在使用IN时,计算的次序更容易管理(因为使用的操作符更少)。 IN操作符一般比OR操作符清单执行更快。
-- 3.IN的最大优点是可以包含其他SELECT语句,使得能够更动态地建立WHERE子句。
-- NOT操作符
-- 否定它之后的所有条件,类似于取反
select * from products p where p.vend_id not in(1002,1003);
-- 这个sql不会输出vendid为1002或1003的行了
第8章 利用通配符进行过滤
知识点:利用like操作符进行通配搜索
本章介绍了什么是通配符以及如何在WHERE 子句中使用 SQL 通配符
并且还说明了通配符应该细心使用,不要过度使用。
百分号通配符
-- Like操作符
-- 利用通配符和like关键字来搜索特定数据(比如包含anvil的产品)
-- (1)百分号%通配符
-- %在搜索串中表示:任何字符出现的任意次数
-- 搜索以jet为开头的产品
select * FROM products p where p.prod_name like 'jet%';
-- 在这个例子里使用了搜索模式‘jet%’,执行语句时,将搜索任意以jet起头的词,%告诉Mysql接受jet之后的任意字符串。
-- 通配符也可以在任意位置使用,也可以使用多个,但通常位于搜索串的两端
select * FROM products p where p.prod_name like '%anvil%';
-- '%anvil%'表示匹配任何位置包含文本anvil的值
select * FROM products p where p.prod_name like 's%e';
-- 也可以放在中间,表示寻找s开头e结尾的数据
--重要的是要注意到,除了一个或多个字符外,%还能匹配0个字符。%代表搜索模式中给定位置的0个、1个或多个字符。
下划线通配符
-- 下划线'_'通配符
-- 下划线通配符可以匹配单个字符而不是多个字符
SELECT * FROM products p WHERE p.prod_name LIKE '_ ton anvil';
-- 和%可以匹配多个字符或0个字符不同,下划线总是匹配一个字符,不能多也不能少
使用通配符的技巧
正如所见, MySQL 的通配符很有用。但这种功能是有代价的:通配符搜索的处理一般要比前面讨论的其他搜索所花时间更长。这里给出一 些使用通配符要记住的技巧。
- 不要过度使用通配符。如果其他操作符能达到相同的目的,应该 使用其他操作符。
- 在确实需要使用通配符时,除非绝对有必要,否则不要把它们用在搜索模式的开始处。把通配符置于搜索模式的开始处,搜索起来是最慢的。
- 仔细注意通配符的位置。如果放错地方,可能不会返回想要的数
第九章 正则表达式
正则表达式是用来匹配文本的特殊的串(字符集合)。如果你想从一个文本文件中提取电话号码,可以使用正则表达式。如果你需要查找名字中间有数字的所有文件,可以使用一个正则表达式。如果你想在一个文本块中找到所有重复的单词,可以使用一个正则表达式。如果你想替换一个页面中的所有URL为这些URL的实际HTML链接,也可以使用一个正则表达式(对于最后这个例子,或者是两个正则表达式)。
-- 基本字符匹配
SELECT * FROM products p WHERE p.prod_name REGEXP '1000' ORDER BY p.prod_name;
-- 这句话其实还看不出来太多优势,但是下面这个例子可以看出一二
SELECT * FROM products p WHERE p.prod_name REGEXP '.000' ORDER BY p.prod_name;
-- '.'表示匹配任意一个字符,因此1000和2000都可以匹配返回
LIKE 与 REGEXP 在 LIKE 和 REGEXP 之间有一个重要的差别。请
看以下两条语句 :
如果执行上述两条语句,会发现第一条语句不返回数据,而第
二条语句返回一行。为什么?
正如第 8 章所述, LIKE 匹配整个列。如果被匹配的文本在列值
中出现, LIKE 将不会找到它,相应的行也不被返回(除非使用
通配符)。而 REGEXP 在列值内进行匹配,如果被匹配的文本在
列值中出现, REGEXP 将会找到它,相应的行将被返回。这是一
个非常重要的差别。
那么, REGEXP 能不能用来匹配整个列值(从而起与 LIKE 相同 的作用)?答案是肯定的,使用 ^ 和 $ 定位符( anchor )即可,
本章后面介绍。
-- 进行OR匹配 在搜索两个条件之一时使用'|'
-- 搜索prod_name中带有1000或2000的
SELECT * FROM products p where p.prod_name REGEXP '1000|2000' ORDER BY p.prod_name;
-- 匹配几个字符之一
-- 使用'[]',把'[]'括起来的字符作为匹配条件
-- 在这行语句里,只会返回prod_name前缀为 1 Ton 或 2 Ton 和 3 Ton的结果
SELECT * FROM products p where p.prod_name REGEXP '[123] Ton' ORDER BY p.prod_name;
-- 匹配范围
-- 如果要匹配一个或多个字符。例如[0123456789],可以简写为[0-9],不限定范围[3-6],也不一定是数值[a-z]
SELECT * FROM products p where p.prod_name REGEXP '[1-5] Ton' ORDER BY p.prod_name;
-- 匹配特殊字符
-- 正则表达式语言由具有特定含义的特殊字符构成。我们已经看到.、[]、 |和-等,还有其他一些字符。请问,如果你需要匹配这些字符,应该怎么
-- 办呢?例如,如果要找出包含.字符的值,怎样搜索?请看下面的例子:
-- 找出vend_name中含有'.'的结果
SELECT * FROM vendors v where v.vend_name REGEXP '.' ORDER BY v.vend_name;
-- 但是'.'在之前提到过,是匹配任意一个单一字符,所以这里需要加上'\\.'来转换语义
SELECT * FROM vendors v where v.vend_name REGEXP '\\.' ORDER BY v.vend_name;
-- 匹配字符类
-- 存在找出你自己经常使用的数字,所有字母字符或所有数字字母字符等的匹配。为更方便工作
-- 可以使用预定义的字符集,成为字符类(character class)
目前为止使用的所有正则表达式都试图匹配单次出现。如果存在一
个匹配,该行被检索出来,如果不存在,检索不出任何行。但有时需要
对匹配的数目进行更强的控制。例如,你可能需要寻找所有的数,不管
数中包含多少数字,或者你可能想寻找一个单词并且还能够适应一个尾
随的 s (如果存在),等等。
-- 匹配多个实例
SELECT p.prod_name FROM products p where p.prod_name REGEXP '\\([0-9] sticks?\\)' ORDER BY p.prod_name;
-- '\\([0-9] sticks?\\)' 细说一下这个正则表达式
-- ‘\\’ 代表匹配
-- '[0-9]'匹配任意数字
-- 'sticks?' 匹配 stick或sticks 's'之后的'?'代表s是可选项,有没有都可以匹配成功
-- 匹配连在一起的四位数字
SELECT p.prod_name FROM products p where p.prod_name REGEXP '[[:digit:]]{4}' ORDER BY p.prod_name;
-- '[[:digit:]]{4}'
-- [:digit:]即[0-9] 代表任意数字
-- {4}确切地要求他前面的字符出现4次!
SELECT p.prod_name FROM products p where p.prod_name REGEXP '[0-9][0-9][0-9][0-9]' ORDER BY p.prod_name;
-- 这个正则表达式与上面的同义
目前为止的所有例子都是匹配一个串中任意位置的文本。为了匹配 特定位置的文本,需要使用表 9-4 列出的定位符。
例如,如果你想找出以一个数(包括以小数点开始的数)开始的所有产品,怎么办?简单搜索 [0-9\\.] (或 [[:digit:]\\.] )不行,因为它将在文本内任意位置查找匹配。解决办法是使用 ^ 定位符
-- 找出以0-9为开头的数(包括有小数点的)
SELECT * FROM products p where p.prod_name REGEXP '^[0-9\\.]';
第十章创建计算字段
-- 使用concat函数,将商品名和供应商的国家拼接在一起
SELECT CONCAT(v.vend_name,'(',v.vend_country,')')FROM vendors v ORDER BY v.vend_name;
-- 配合RTrim进行整理
SELECT CONCAT(RTRIM(v.vend_name),'(',RTRIM(v.vend_country),')')FROM vendors v ORDER BY v.vend_name;
另外,还可以在查询语句里执行一些算数操作
SELECT
oi.prod_id,
oi.quantity,
oi.item_price,
( oi.item_price * oi.quantity ) expanded_price
FROM
orderitems oi
WHERE
oi.order_num = 20005;
第十一章 使用数据处理函数
sql的函数分为:
- 处理文本串
- 数值数据上的算术操作
- 处理日期和时间值并从这些值中提取特定成分的日期和时间函数
- 返回DBMS正式用的特殊信息
文本处理函数
-- Upper()函数 字母转换为大写
SELECT
v.vend_name,
UPPER( v.vend_name ) 字母转换为大写
FROM
vendors v
ORDER BY
v.vend_name;
-- Length()函数 返回串的长度
SELECT
v.vend_name,
Length( v.vend_name ) 返回串的长度
FROM
vendors v
ORDER BY
v.vend_name;
日期处理函数
MySQL 查询时间段内的数据
-- 日期计算
-- 找到日期为2005-09-01的订单
SELECT * FROM orders o where o.order_date = '2005-09-01';
-- 但有可能还存储了时分秒,所以最好用Date()函数转化一下再进行匹配
SELECT * FROM orders o where DATE(o.order_date) = '2005-09-01';
-- 找出9月份的订单
SELECT * FROM orders o where DATE(o.order_date) BETWEEN '2005-09-01' AND '2005-09-30';
-- 或者可以用函数式的方法
SELECT * FROM orders o where YEAR(o.order_date) = 2005 AND MONTH(o.order_date) = 9;
数值处理函数
第十二章 汇总数据
-- AVG函数
SELECT AVG(p.prod_price) 不去重,AVG(DISTINCT p.prod_price) 去重 FROM products p;
-- MAX函数
SELECT MAX(p.prod_price) FROM products p;
-- MIN函数
SELECT MIN(p.prod_price) FROM products p;
-- COUNT函数
SELECT COUNT(p.prod_price) FROM products p;
-- SUM函数
SELECT SUM(p.prod_price) FROM products p;
第十三章 分组数据
-- 根据供应商将货品id分组
SELECT
p.vend_id,
COUNT( * ) AS num_prods
FROM
products p
GROUP BY
p.vend_id
ORDER BY
p.vend_id
可以用having来替代where进行条件检索
-- 过滤分组
SELECT
o.cust_id,
COUNT( * ) orders
FROM
orders o
GROUP BY
o.cust_id
HAVING
COUNT( * ) >= 2;
having是用来处理分组后的数据,where是处理分组前的数据
-- Having和where
SELECT
p.vend_id,
COUNT( * ) AS num_prods
FROM
products p
WHERE
p.prod_price >= 10
GROUP BY
p.vend_id
HAVING
COUNT(*) > 2
ORDER BY
p.vend_id
第十四章 使用子查询
-- 查出订购了TNT2物品的所有客户
SELECT
c.*
FROM
customers c
WHERE
cust_id IN ( SELECT o.cust_id FROM orders o WHERE o.order_num IN ( SELECT oi.order_num FROM orderitems oi WHERE oi.prod_id = 'TNT2' ) );
使用计算字段作为子查询
-- 使用计算字段作为子查询
SELECT
c.cust_id,
c.cust_name,
(SELECT COUNT(*) FROM orders o WHERE o.cust_id = c.cust_id) as orders
FROM
customers c
ORDER BY
orders DESC