mysql 必知必会整理—sql 排序与过滤[三]
前言
简单整理一下MySQL的排序与过滤。
正文
我们查询出来的结果有时候是希望进行排序的,比如说:
select product_name
from products
order by prod_name
经常需要按不止一个列进行数据排序。例如,如果要显示雇员清单,可能希望按姓和名排序(首先按姓排序,然后在每个姓中再按名排序)。如果多个雇员具有相同的姓,这样做很有用。
这里面就是先按照prod_price,如果prod_price 相同的话,那么按照prod_name来。
数据排序不限于升序排序(从A到Z)。这只是默认的排序顺序,还可以使用ORDER BY子句以降序(从Z到A)顺序排序。为了进行降序排序,必须指定DESC关键字。
注意:
在多个列上降序排序 如果想在多个列上进行降序排序,必须
对每个列指定DESC关键字。
区分大小写和排序顺序 在对文本性的数据进行排序时,A与 a相同吗?a位于B之前还是位于Z之后?这些问题不是理论问
题,其答案取决于数据库如何设置。
在字典(dictionary)排序顺序中,A被视为与a相同,这是MySQL
(和大多数数据库管理系统)的默认行为。但是,许多数据库
管理员能够在需要时改变这种行为(如果你的数据库包含大量
外语字符,可能必须这样做)。
这里,关键的问题是,如果确实需要改变这种排序顺序,用简
单的ORDER BY子句做不到。你必须请求数据库管理员的帮助。
过滤语句,一般指的是where 子句。
数据库表一般包含大量的数据,很少需要检索表中所有行。通常只
会根据特定操作或报告的需要提取表数据的子集。只检索所需数据需要
指定搜索条件(search criteria),搜索条件也称为过滤条件(filter
condition)。
一般使用where 来进行过滤。
比如说:
select *
from product
where price>100
表示过滤出100的价格。
SQL过滤与应用过滤 数据也可以在应用层过滤。为此目
的,SQL的SELECT语句为客户机应用检索出超过实际所需的
数据,然后客户机代码对返回数据进行循环,以提取出需要
的行。
通常,这种实现并不令人满意。因此,对数据库进行了优化,
以便快速有效地对数据进行过滤。让客户机应用(或开发语言)
处理数据库的工作将会极大地影响应用的性能,并且使所创建
的应用完全不具备可伸缩性。此外,如果在客户机上过滤数据,
服务器不得不通过网络发送多余的数据,这将导致网络带宽的
浪费。
where 子句通常有操作符。
这里需要注意的是一个null值,NULL 无值(no value),它与字段包含0、空字符串或仅仅包含
空格不同。
可以看到这里显示的是is,而不是==,至于为什么可以查看我的整理1800篇sql语句中查看。
NULL与不匹配 在通过过滤选择出不具有特定值的行时,你
可能希望返回具有NULL值的行。但是,不行。因为未知具有
特殊的含义,数据库不知道它们是否匹配,所以在匹配过滤
或不匹配过滤时不返回它们。
因此,在过滤数据时,一定要验证返回数据中确实给出了被
过滤列具有NULL的行。
在使用where的时候,我们一般要知道另外交给关键词,and or in not 这几个操作符号。
and 例子:
OR操作符与AND操作符不同,它指示MySQL检索匹配任一条件的行。
or 例子:
WHERE可包含任意数目的AND和OR操作符。允许两者结合以进行复杂和高级的过滤。
但是,组合AND和OR带来了一个有趣的问题。
先说一下其本来的意思,其查询条件为vend_id=1002或者vend_id 为1003的,且价格要大于10元的。
但是按照上面的指示,
SQL(像多数语言一样)在处理OR操作符前,优先处理AND操
作符。当SQL看到上述WHERE子句时,它理解为由供应商1003制造的任何
价格为10美元(含)以上的产品,或者由供应商1002制造的任何产品,
而不管其价格如何。换句话说,由于AND在计算次序中优先级更高,操作
符被错误地组合了。
此问题的解决方法是使用圆括号明确地分组相应的操作符。请看下
面的SELECT语句及输出:
在WHERE子句中使用圆括号 任何时候使用具有AND和OR操作
符的WHERE子句,都应该使用圆括号明确地分组操作符。不要
过分依赖默认计算次序,即使它确实是你想要的东西也是如
此。使用圆括号没有什么坏处,它能消除歧义。
下面介绍一下in 操作符:
圆括号在WHERE子句中还有另外一种用法。IN操作符用来指定条件范
围,范围中的每个条件都可以进行匹配。IN取合法值的由逗号分隔的清
单,全都括在圆括号中。下面的例子说明了这个操作符:
此SELECT语句检索供应商1002和1003制造的所有产品。IN操作符后跟由逗号分隔的合法值清单,整个清单必须括在圆括号中
in 和 or 有相同的效果,那么有时候为什么要使用in呢?
在使用长的合法选项清单时,IN操作符的语法更清楚且更直观。
在使用IN时,计算的次序更容易管理(因为使用的操作符更少)。
IN操作符一般比OR操作符清单执行更快。
IN的最大优点是可以包含其他SELECT语句,使得能够更动态地建
立WHERE子句。
这里的NOT否定跟在它之后的条件,因此,MySQL不是匹配1002
和 1003 的 vend_id ,而是匹配 1002 和 1003 之外供应商的
vend_id。
这里再介绍两个东西,一个是exits和 not exits。
exit 其实用的不多,因为其替代性强。
比如:
要求:查询选修了课程”操作系统“的同学
select sname from student
where exits (select * from sc,course where sno = student.sno and sc.cno = course.cno and course.cname ="操作系统")
完全可以这样替代:
select * from sc,course,student where sc.sno = student.sno and sc.cno = course.cno and course.cname ="操作系统"
但是如果是现在需求是这样的:
查询没有选修课程”操作系统“的同学
select sname from student
where not exits (select * from sc,course where sno = student.sno and sc.cno = course.cno and course.cname ="操作系统")
这样似乎有点艰难吧,可能有些初学者认为这样:
select * from sc,course,student where sc.sno = student.sno and sc.cno = course.cno and course.cname !="操作系统"
这当然是不对的啦,因为是先做笛卡儿积,然后再做where过滤,这样当然是不满足条件的了。