SQL检索数据的超全教程 1
检索数据
写在前面,sql语句是不区分大小写的,SELECT和select是一样的,但是许多的SQL开发人员习惯对sql关键字大写,而对所有的列和表名使用小写。
select语句
检索单个列
select prod_name from products;
检索多个列
SELECT prod_id , prod_name,prod_price FROM products;
检索所有列
SELECT * FROM products;
检索不同行
使用DISTINCT关键字使得返回的信息是不同的行信息。
但是你不能这样:
除非两个列相同,否则所有行信息都会被展示出来。
限制结果
SELECT语句返回所有匹配的行。为了返回第一行或者前几行,可使用LIMIT子句
SELECT prod_name FROM products LIMIT 5;
SELECT prod_name FROM products LIMIT 5,5;
LIMIT 5 , 5代表的是从行5开始的5行。
行0:检索出来第一行为行0而不是行1。LIMIT 1,1检索出来的是第二行,而不是第一行。
行不够时,如LIMIT 10,5, 。如果只有13行时,mysql只能返回他能返回的行数了就。
MySQL 5的LIMIT语法。LIMIT 4 OFFSET 3 表示从行3开始取4行。
使用完全限定的表明
这里其实就是指,把列名通过表明限定,甚至把表明通过数据库名来完全限定。
SELECT products.prod_name FROM bizhibihui.products;
排序检索数据 (ORDER BY)
排序数据
子句:之前写到的FROM就算是SELECT的一个子句。为了明确排序顺序所以我们可以使用 ORDER BY子句。
SELECT prod_name FROM products ORDER BY prod_name;
这样上面的搜索结果就实现了字母排序。
上面ORDER BY 子句使用的列是检索列,其实不使用检索的列进行排序也是完全合法的。
按多个列排序
我们在现实生活中也会遇到这样的情况:比如你说按姓名排序,当姓一样的时候,你就需要按名字来排序
SELECT prod_id , prod_price ,prod_name
FROM products
ORDER BY prod_price,prod_name;
上面的结果就可以观察到,当价格一样的时候,就会按照产品名称排序。
指定排序方向 (DESC 降序)
数据排序不仅限于升序排序(从A到Z),这只是默认的排序顺序。我们还可以使用降序排序关键字DESC
SELECT prod_id,prod_price,prod_name
FROM products
ORDER BY prod_price DESC;
上面的图片就实现了价格的降序排序。
打算对多个列排序怎么办呢?
SELECT prod_id,prod_price,prod_name
FROM products
ORDER BY prod_price DESC,prod_name;
上面就实现了先对价格降序,然后价格相同的按名字升序。
DESC关键词只应用到直接位于其前面的列名。所以如果你想对多个列进行降序排序,必须每个列指定DESC关键字。
ASC是升序关键词,但其实是没有什么用处的,因为默认就是升序呀。
例子:找出最昂贵的物品
SELECT prod_price
FROM products
ORDER BY prod_price DESC
LIMIT 1;
过滤数据 (WHERE 子句)
使用WHERE 子句
我们很少需要检索表中的所有行,通常会根据特定操作或报告的需要提取数据的子集。
在SELECT语句中,数据根据WHERE子句中指定的搜索条件进行过滤。WHERE子句在表名(FROM子句)之后给出。
SELECT prod_name ,prod_price
FROM products
WHERE prod_price=2.50;
只展示价格为2.50的产品。
WHERE子句的位置:在同时使用ORDER BY和WHERE子句时,应该让ORDER BY位于WHERE之后,否则将会产生错误。
WHERE子句操作符
WHERE子句操作符 | 说明 |
---|---|
= | 等于 |
<> | 不等于 |
!= | 不等于 |
< | 小于 |
<= | 小于等于 |
> | 大于 |
>= | 大于等于 |
BETWEEN | 在指定的两个值之间 |
检查单个值:
SELECT prod_name,prod_price
FROM products
WHERE prod_name = 'fuses';
SELECT prod_name,prod_price
FROM products
WHERE prod_price < 10;
不匹配检查:
SELECT vend_id,prod_name
FROM products
WHERE vend_id<>1003;
范围值检查:
SELECT prod_name ,prod_price
FROM products
WHERE prod_price BETWEEN 5 AND 10;
从上面的结果可以看出来这个BETWEEN的范围是闭区间
空值检查:
SELECT cust_id
FROM customers
WHERE cust_email IS NULL;
:heavy_exclamation_mark:一定要注意一点,空值不是0。
:heavy_exclamation_mark:过滤与不匹配:在通过过滤选择出不匹配值的行中,你可能希望可以返回具有NULL值的行,但是,不行。
数据过滤
组合WHERE子句
之前的WHERE子句都是单一的条件,其实是可以使用多个WHERE子句的,这些子句可以使用AND和OR子句的方式使用。
AND操作符
为了通过不止一个列进行过滤,可使用AND操作符给WHERE子句附加条件。
SELECT prod_id , prod_price, prod_name
FROM products
WHERE vend_id = 1003 AND prod_price <= 10;
OR操作符
检索匹配任一条件的行。
SELECT prod_name,prod_price
FROM products
WHERE vend_id = 1002 OR vend_id = 1003;
AND的计算次序优先级更高
为了解决这一问题,方法就是加圆括号()
IN操作符
IN操作符用来指定条件范围,范围内的每个条件都可以进行匹配,IN取合法值的由逗号隔开。
SELECT prod_name ,prod_price
FROM products
WHERE vend_id IN (1002,1003)
ORDER BY prod_name;
如果你认为IN和OR功能相同,这种想法是正确的。下面就是晚上上面的同样的工作。
SELECT prod_name ,prod_price
FROM products
WHERE vend_id = 1002 OR vend_id = 1003
ORDER BY prod_name;
那为什么选择IN呢?
在使用长的合法选项清单时,IN操作符的语法更清楚更直观
在使用IN时,计算次序更容易管理
IN操作符一般比OR操作符清单执行的更快
IN的最大优点是可以包含其他SELECT 语句,使得能够更动态地建立WHERE子句。
NOT操作符
NOT功能:否定他之后所跟的任何条件。
SELECT prod_name,prod_price
FROM products
WHERE vend_id NOT IN (1002,1003)
ORDER BY prod_name;
用通配符进行过滤
LIKE操作符
LIKE指示MySQL后跟的搜索模式利用通配符匹配而不是直接相等匹配进行比较
%百分号通配符
%表示任何字符出现任意次数。、
例:为了找出以词jet起头的产品:
SELECT prod_id,prod_name
FROM products
WHERE prod_name LIKE 'jet%';
例:通配符可以在搜索模式的任意位置使用,并且可以使用多个通配符。
SELECT prod_id,prod_name
FROM products
WHERE prod_name LIKE '%anvil%';
🏳️🌈需要注意的是,%是可以匹配0个字符的。%代表搜索模式中给定位置的0个,1个,或多个字符。
🉐还需要注意的一点是,尾部空格是会干扰通配符的匹配的。如果在保存anvil时尾部有几个空格,‘%anvil’就没有办法匹配成功的。解决方法就是你在末尾也加上一个%。或者更好的方法是使用函数。
🏢虽然似乎%可以匹配任何东西,但是有一个例外,那就是NULL。即使是WHERE prod_name LIKE '%'也不能匹配用值为NULL的产品名。
_下划线通配符
下划线只匹配单个字符。
SELECT prod_id ,prod_name
FROM products
WHERE prod_name LIKE '_ ton anvil';
📧和%不一样,下划线只能匹配一个字符,不能多也不能少。
使用通配符的技巧
- 不要过度使用通配符,如果其他操作符能达到同样的目的,应该使用其他的操作符。
- 在确实需要使用统配符的时候,尽量不要把他们用到搜索模式的开始处。把通配符置于搜索模式的开始处,搜索起来是最慢的。
- 仔细注意通配符的位置。如果放错地方,可能不会返回想要的数据。
用正则表达式进行搜索
使用MySQL正则表达式
基本字符匹配
例:检索列prod_name 包含文本1000的所有行。
SELECT prod_name
FROM products
WHERE prod_name REGEXP '1000'
ORDER BY prod_name;
💛REGEXP告诉MySQL,它后面跟着的是正则表达式。
SELECT prod_name
FROM products
WHERE prod_name REGEXP '.000'
ORDER BY prod_name;
⚠️这个 . 可以说是正则表达式的一部分用途了。它表示匹配任一一个字符。
LIKE 和 REGEXP的区别
- LIKE是匹配整个列,完全一样或者带通配符才可以匹配成功
- REGEXP是只要列中包含文本就可以匹配成功。当然REGEXP也可以匹配整个列值。
区分大小写
正则表达式的匹配是不区分大小写的。为区分大小写可使用BINARY关键字。
- 如:WHERE prod_name REGEXP BINARY ‘JetPack .000’
进行OR匹配
使用符号 |
SELECT prod_name
FROM products
WHERE prod_name REGEXP '1000|2000'
ORDER BY prod_name;
匹配几个字符串之一
如果你只想匹配特定的字符,可以通过指定一组用 [ ] 括起来的字符完成。
SELECT prod_name
FROM products
WHERE prod_name REGEXP '[123] Ton'
ORDER BY prod_name;
上面这个结果,还想说明一个问题,就是REGEXP虽然是可以匹配尾巴和头部的空格,但是你在单引号之间的空格还是需要你自己写上去的,单引号之间的空格你不写可是匹配不到结果的。
如上面结果所示,[]其实就是另一种方式的or语句,【123】其实也就是【1|2|3】。当然你写后者也是没有任何问题的。
下面我们再看一个例子:
SELECT prod_name
FROM products
WHERE prod_name REGEXP '1|2|3 Ton'
ORDER BY prod_name;
从结果上我们不难看出,你不用【】括起来,MySQL就会理解为1or2or3 Ton这样的形式
而下面那三行能匹配到也就是因为里面有1or2。
⚠️字符集也可以被否定:[ ^123 ]的意思就是匹配除了这些以外的任何东西。
这个 ^ 在【】括号里,就是除了的1,2,3,的意思,但是如果没有【】,那就是定位符是文本的开始位置的意思。
你比如说下面这两结果就是一样的哟:
你再看一个理解定位符^
当时我有一个这样的例子不明白,后来想明白了。
上面这个当时我就不明白,为什么都不包含1了,红框里还有,这就是REGEXP,你不包含1or2or3.你有其他的元素呀,所以你就得显示出来。
匹配范围
集合可以用来定义要匹配的一个或者多个字符。
例如:下面的集合将匹配数字0到9
【0123456789】
为了简化这种类型的集合,可使用 - 来定义一个范围。
【0-9】
SELECT prod_name
FROM products
WHERE prod_name REGEXP '[1-5] Ton'
ORDER BY prod_name;
匹配特殊字符
也就是转义。我们要匹配特殊字符必须用\为前导。
SELECT vend_name
FROM vendors
WHERE vend_name REGEXP '\.'
ORDER BY vend_name;
⚠️多数的正则表达式实现使用单个反斜杠转义特殊字符,以便能使用这些字符本身。但是mysql要求两个反斜杠(mysql自己解释一个,正则表达式库解释一个)。
匹配字符类
存在找出你自己经常使用的数字,所有字母字符或所有数字字母字符等的匹配。为方便工作,可以使用预定义的字符集,称为字符类。
类 | 说明 |
---|---|
【:alnum:】 | 任意字母和数字(同【a-zA-Z0-9】) |
【:alpha:】 | 任意字符【a-zA-Z】 |
【:blank:】 | 空格和制表【\t】 |
[:cntrl:] | ASCII控制字符(ASCII0到31和127) |
【:digit:】 | 任意数字(【0-9】) |
【:graph:】 | 与【:print:】相同,但不包括空格 |
【:lower:】 | 任意小写字母【a-z】 |
【:print:】 | 任意可打印字符 |
【:punct:】 | 既不在【:alnum:】也不在【:cntrl:】中的任意字符 |
【:space:】 | 包括空格在内的任意空白符(同【\f\n\r\t\v】) |
[:upper:] | 任意大写字母【A-Z】 |
【:xdigit:】 | 任意十六进制数字(同【a-fA-F0-9】) |
匹配多个实例
重复元字符
元字符 | 说明 |
---|---|
* | 0个或者多个匹配 |
+ | 1个或多个匹配(等于{1,}) |
? | 0个或1个匹配(等于{0,1}) |
{n} | 指定数目的匹配 |
{n,} | 不少于指定数目的匹配 |
{n,m} | 匹配数目的范围 |
SELECT prod_name
FROM products
WHERE prod_name REGEXP '\([0-9] sticks?\)'
ORDER BY prod_name;
🎃我觉得难理解的点就在于,那个?的匹配(s后的?使s可选,因为?匹配他前面的的任何字符0次或者1次)。这也就是会有第一条结果的原因。
例:匹配连在一起的的4位数字。
SELECT prod_name
FROM products
WHERE prod_name REGEXP '[[:digit:]]{4}'
ORDER BY prod_name;
定位符
之前的例子都是匹配任一一个串中任意位置的文本。为了匹配特定位置的文本,我们需要使用定位符。
元字符 | 说明 |
---|---|
^ | 文本的开始 |
$ | 文本的结束 |
[[:<:]] | 词的开始 |
[[:>:]] | 词的结束 |
例:找一个以数或小数点开始的所有产品
SELECT prod_name
FROM products
WHERE prod_name REGEXP '^[0-9\.]'
ORDER BY prod_name;
创建计算字段
计算字段
存储在表中的数据都不是应用程序所需要的。我们需要直接从数据库中检索出转换计算,格式化后的数据。这就是计算字段发挥作用的所在了。计算字段并不实际存在于数据库表中。计算字段是在运行SELECT时语句内创建的。
拼接字段
我们需要输出这样的一个格式 name(location),但数据库中是没有这样的字段的,所以我们需要拼接列来显示一个这样的信息。
解决方法:我们使用Concat函数来拼接两个列
SELECT Concat(vend_name,'(',vend_country,')')
FROM vendors
ORDER BY vend_name;
RTrim函数去掉值右边的所有空格,通过使用RTrim()。各个列都进行了整理。
SELECT Concat(RTrim(vend_name),'(',RTrim(vend_country),')')
FROM vendors
ORDER BY vend_name;
:parasol_on_ground:LTrim呢,显而易见就是去除串左边的空格。
:sailboat:Trim,去除串左右两边的空格。
刚刚的输出我们可以看到那个表头是很不美观的,所以我们可以使用别名
AS别名
SELECT Concat(RTrim(vend_name),'(',RTrim(vend_country),')') AS vend_title
FROM vendors
ORDER BY vend_name;
执行算术计算
我们可以在SELECT语句中就添加一些算数计算,以计算一些列的值。
SELECT prod_id,quantity,item_price,quantity*item_price AS expanded_price
FROM orderitems
WHERE order_num = 20005;
使用数据处理函数
函数
函数没有SQL的可移植性强
使用函数
文本处理函数
:mag:Upper()函数:将文本转化为大写
SELECT vend_name ,Upper(vend_name) AS vend_name_upcase
FROM vendors
ORDER BY vend_name;
常用的文本处理函数
函数 | 说明 |
---|---|
Left() | 返回串左边的字符 |
Length | 返回串的长度 |
Locate() | 找出串的一个子串 |
Lower() | 将串转换为小写 |
LTrim() | 去掉串左边的空格 |
Right() | 返回串右边的字符 |
RTrim() | 去掉串右边的空格 |
Soundex() | 返回串的SOUNDEX值 (这玩意是发音类似匹配) |
SubString() | 返回子串的字符 |
Upper() | 将串转换为大写 |
日期和时间处理函数
常用日期和时间处理函数
函数 | 说明 |
---|---|
AddDate() | 增加一个日期(天,周等) |
AddTime() | 增加一个时间(时,分等) |
CurDate() | 返回当前日期 |
CurTime() | 返回当前时间 |
Date() | 返回日期时间的日期部分 |
DateDiff() | 计算两个日期之差 |
Date_Add() | 高度灵活的日期运算函数 |
Date_Format() | 返回一个格式化的日期或时间串 |
Day() | 返回一个日期的天数部分 |
DayOfWeek() | 对于一个日期返回对应的星期几 |
Hour() | 返回一个时间的小时部分 |
Minute() | 返回一个时间的分钟部分 |
Month() | 返回一个日期的月份部分 |
Now() | 返回当前日期和时间 |
Second() | 返回一个时间的秒部分 |
Time() | 返回一个日期时间的时间部分 |
Year() | 返回一个日期的年份部分 |
SELECT cust_id,order_num
FROM orders
WHERE Date(order_date) = '2005-09-01';
加Date()是一个好习惯,即使你知道表里只有日期,但是这样的方式可以万无一失,万一以后表里加入时间,也不会出现匹配不到的错误。
例:如果你想检索出2005年9月下的所有订单。
法一:
SELECT cust_id,order_num
FROM orders
WHERE Date(order_date) BETWEEN '2005-09-01'AND '2005-09-30';
法二:
SELECT cust_id ,order_num
FROM orders
WHERE Year(order_date) = 2005 AND Month(order_date) = 9;
数值处理函数
常用的数值处理函数
函数 | 说明 |
---|---|
Abs() | 返回一个数的绝对值 |
Cos() | 返回一个角度的余弦 |
Exp() | 返回一个数的指数值 |
Mod() | 返回除操作的余数 |
Pi() | 返回圆周率 |
Rand() | 返回一个随机数 |
Sin() | 返回一个角度的正弦 |
Sqrt() | 返回一个数的平方根 |
Tan() | 返回一个角度的正切 |
- 点赞
- 收藏
- 关注作者
评论(0)