数据库最普遍的操作就是"插、查、删,改"。在前在的日志中,我为大家介绍过MySQL的 insert 插入语句,也为大家介绍过 update 更新语句,以及删除语句 delete 和 truncate语句。今天就为大家来介绍一下,MySQL中唯一的检索数据语句:select语句。
select 语句是SQL开发者最常用的语句,也是最强大的武器,幸运在的是,学习这个语句并不是很难。
select 语句的定义:
一切都要遵循规矩来办事,所以和之前的教程一样,我们先来看一下手册上面说的 select 语句的语法结构:
代码如下 | 复制代码 |
SELECT [ALL | DISTINCT | DISTINCTROW ] [HIGH_PRIORITY] [STRAIGHT_JOIN] [SQL_SMALL_RESULT] [SQL_BIG_RESULT] [SQL_BUFFER_RESULT] [SQL_CACHE | SQL_NO_CACHE] [SQL_CALC_FOUND_ROWS] select_expr, ... [INTO OUTFILE 'file_name' export_options | INTO DUMPFILE 'file_name'] [FROM table_references [WHERE where_definition] [GROUP BY {col_name | expr | position} [ASC | DESC], ... [WITH ROLLUP]] [HAVING where_definition] [ORDER BY {col_name | expr | position} [ASC | DESC] , ...] [LIMIT {[offset,] row_count | row_count OFFSET offset}] [PROCEDURE procedure_name(argument_list)] [FOR UPDATE | LOCK IN SHARE MODE]] |
呵呵,看到了吧?其语法是相当的长了,但是有一点大家要知道,中括号内部的是可以省略的。有的时候是用不到这些东西的。我们一点点来,不要被这语法吓到,其实 select 语句还是很简单的,之所以语法这么复杂, 那是因为 select 语句是非常强大的。
select 执行数学运算:
我们可以使用select语句来执行数学运算,当然,如果公式太复杂的话就算了,否则数学学家不就死绝了?哈哈。 简单给大家几个例子,说明一下问题就行,至于一百以内的加减法咱就自己算了,就不麻烦 MySQL 了哈。呵呵。
代码如下 | 复制代码 |
select 100 + 100, 50>=(2+3) , 100/3; /* +-----------+-----------+---------+ | 100 + 100 | 50>=(2+3) | 100/3 | +-----------+-----------+---------+ | 200 | 1 | 33.3333 | +-----------+-----------+---------+ 1 row in set (0.00 sec) */ |
select 检索指定的行和列:
select 语句支持 * 通配符,表示获得所有的字段。同时,也支持用户自己指定字段名,来返回指定的列。例如,如下语句返回的是之前用过的 twitter 插件的所有数据列,就可以使用 * 这个通配符。
代码如下 | 复制代码 |
select * from wp_threadtwitter_users G ; /* *************************** 1. row *************************** id: 16628009 name: simaopig screen_name: simaopig location: description: profile_image_url: http://s3.amazonaws.com/twitter_production/profile_images/180700745/head_normal.png url: http://www.111cn.net protected: 1 followers_count: 1 1 row in set (0.00 sec) */ |
如果我只想看其中的 url 和 name 字段的所有信息就可以使用如下语句,将返回的结果集指定所要展示的列的字段名:
代码如下 | 复制代码 |
select name,url from wp_threadtwitter_users ; /* +----------+---------------------------+ | name | url | +----------+---------------------------+ | simaopig | http://www.111cn.net | +----------+---------------------------+ 1 row in set (0.00 sec) */ |
select 为查询结果加上限制条件:
我们可以使用where子句来为select语句指定所要查询的限制条件,只要满足where子句的结果才会展示在结果集中,例如下面语句,我希望从wp_threadtwitter_users 中只返回name为simaopig的用户的url,就可以使用如下语句:
代码如下 | 复制代码 |
select url from wp_threadtwitter_users where name = 'simaopig'; /* +---------------------------+ | url | +---------------------------+ | http://www.111cn.net | +---------------------------+ 1 row in set (0.00 sec) */ |
where子句也可以指定更复杂的范围,比如说,我想查询一下,我发表的日志中,评论数大于30,并且小于50的文章id及title就可以指定如下子句:
代码如下 | 复制代码 |
select id,post_title,comment_count from wp_posts where comment_count > 30 and comment_count < 50 limit 2; /* +-----+-------------------------------------------------------+---------------+ | id | post_title | comment_count | +-----+-------------------------------------------------------+---------------+ | 488 | 海运女,又一个倒霉蛋 | 46 | | 501 | 解决Mail to Commenter发出的邮件被当作垃圾 | 36 | +-----+-------------------------------------------------------+---------------+ 2 rows in set (0.01 sec) */ |
select 使用内建函数:
long long ago,我为大家介绍过MySQL的函数部分,MySQL为大家提供了非常丰富的内建函数来满足大家日常的需要,下面我为大家举两个例子,分别使用 MAX , MIN, COUNT 这三个函数,来返回我发表日志的评论最多的文章,和评论最少的文章,以及我发表日志的总数:
代码如下 | 复制代码 |
select max(comment_count),min(comment_count) from wp_posts; /* +--------------------+--------------------+ | max(comment_count) | min(comment_count) | +--------------------+--------------------+ | 362 | 0 | +--------------------+--------------------+ 1 row in set (0.01 sec) */ |
由上面结果可以看出,我还有文章的沙发保存至今呢。呵呵,哪位有兴趣可以去翻一下,抢一下这落了好多灰的沙发。呵。
代码如下 | 复制代码 |
select count(*) from wp_posts; /* +----------+ | count(*) | +----------+ | 340 | +----------+ 1 row in set (0.00 sec) */ |
由结果可以看出,算上我保存的草稿,本站从建立至今,小小子已经写过340篇日志了,虽然其中草稿占了很大一个比重。呵呵。不过,总是自己一个字一个字敲的。哈。
select 为表取别名:
有的时候,我们要查询的表的名字太长了,经常敲这些名字是很累人的,尤其是我这种懒人,MySQL为我们提供了表的别名机制,使我们在查询的时候可以给表起个别名,大家可以理解为起外号,比如我管"小猫"叫"犊子",那么当我喊"犊子"的时候,某人当然知道我是在叫他。哈。
为表起别名,可以在用select 语句指定查询的表名后面用 as 子句来指定,例如下面我为wp_threadtwitter_users 起别名为 users,并且在后面的查询中,我用别名指定字段,这在子查询中是很方便的,呵
代码如下 | 复制代码 |
select * from wp_threadtwitter_users as users where screen_name like '%mg%' and users.followers_count > 200 G |
select 限制查询结果的个数:
有的时候查询到的结果数目太多了,以至于一个屏幕都显示不下,那我们咋看这结果了?别急,MySQL为我们提供了limit子句,其和select语句一起使用时,可以限制查询结果的个数,limit子句后面直接跟想要取得的结果集的行数,使用方法如下:
代码如下 | 复制代码 |
select id from wp_posts where id > 3 and comment_count > 30 limit 2; /* +-----+ | id | +-----+ | 86 | | 488 | +-----+ */ |
也可以指定一个偏移量,例如,下面的例子从第4行(注意,是从0开始计数的)开始,返回2条记录:
代码如下 | 复制代码 |
select id from wp_posts limit 3,2; /* +----+ | id | +----+ | 26 | | 28 | +----+ 2 rows in set (0.00 sec) */ |
select 对查询结果进行分组和排序:
MySQL提供了order by 和 group by ,结合select 语句,我们可以对查询返回的结果进行排序和分组。可以在order by子句向两个字段添加asc 和 desc关键字来定制排序方法,如果没有指定order by 子句,MySQL对结果集的排序默认为升序。相应字段的值以升序或者降序的顺序被排序。而group by 后面直接跟字段名,意思为按该字段为查询结果分组:
取小小子发表的博客日志的文章id,取3条,按照id来倒序排列:
代码如下 | 复制代码 |
select id from wp_posts order by id desc limit 3; /* +------+ | id | +------+ | 1451 | | 1450 | | 1449 | +------+ 3 rows in set (0.00 sec) */ |
比如下面的例子,我把wordpress的友情链接,按照link_rel分组,来取其中的前两条记录,可以使用如下语句:
代码如下 | 复制代码 |
select link_rel,link_name from wp_links as links group by link_rel limit 2 G /* *************************** 1. row *************************** link_rel: link_name: LAONB *************************** 2. row *************************** link_rel: acquaintance link_name: 衡天小张主机 2 rows in set (0.02 sec) */ |
select 使用变量和子查询:
这节是滥竽充数的,因为本篇日志不对其进行解释,在后面的日志中,小小子会专门写一篇关于MySQL子查询的日志来为大家讲解。至于使用变量嘛,一般用不到,咱就不瞎白话了,免得误人子弟就罪过了。
控制 select 的行为:
可以向select 语句添加很多关键字来修改行为:
•DISTINCT关键字删除包含结果信中具有重复值的记录
•SQL_CALC_FOUND_ROWS关键字告诉MySQL计算符合查询(不需要考虑可能设置的任何LIMIT)的总行数。通过调用FOUND_ROWS()函数可以得到总行数
•SQL_CACHE 和SQL_NO_CACHE关键字告诉MySQL查询结果是否需要高速缓存
•SQL_BUFFER_RESULT关键字强制MySQL把查询结果存储到一个临时表。这使缓冲器消除了对查询所使用的表的锁定,而且结果被传送给客户,因而可以暂被其他进程使用
•SQL_BIG_RESULT 和SQL_SMALL_RESULT关键字可以指定结果集的期望大小,因此可帮助找到最佳的方法对返回的记录进行排序和存储(基于磁盘或者内存中的临时表)
•SQL_HIGH_PRIORITY关键字提升了与UPDATE,INSERT和DELETE语句相竞争的查询的优先级,因而可以在繁忙的数据库服务器上快速的执行查询
生成统计信息
单纯依靠手工来生成统计信息是一项既艰苦又耗时还容易出错的工作,如果我们能熟练掌握用数据库来生成各种统计信息的技巧,他就会成为很有威力的信息处理工具。作者在这里用了许多篇幅讲这个主题,为了便于大家理解,我分解开来论述:
9.1 找出一组数据中到底有多少种不同的值是一项比较常见的统计工作,而关键字distinct就可以把查询结果中的重复数据清除掉。如
代码如下 | 复制代码 |
select distinct state from president //看看美国总统们都来自那些州?(重复的不计) |
9.2用count()函数来统计相关记录的个数,注意其使用方法:count(*)计算所有的,NULL也要;count(数据列名称) NULL值不计算在内。
代码如下 | 复制代码 |
select count(*) from president; |
9.3如果我们想知道班级内的男女生数目?该如何查询呢?最简单的方法是
代码如下 | 复制代码 |
select count(*) from student where sex='f'; select count(*) from student where sex='m |
但是如果使用count函数结合group by关键字,一行命令就搞定了
代码如下 | 复制代码 |
select sex,count(*) f rom student group by sex; |
我们可以看到,与反复使用彼此类似的查询来分别统计某数据列不同取值出现次数的做法相比,把count(*)和group by字句相结合使用有许多优点,主要表现在:
在开始统计自前,不必知道被统计的数据列里面有多少种不同的取值
因为只用了一个查询命令,我们可以对输出做排序的处理
代码如下 | 复制代码 |
select state,count(*) as count from president group by state order by count desc limt4; // |
看看出生总统最多的前四个州是哪几个?
9.4除了count(),我们还用其他一些统计函数,如求出最小值的min(),求最大值的max(),求和的sum(),求平均值的avg(),在实际工作中,这些函数时经常用到的!
*10、从多个表提取信息
我们目前的例子都是从一个表里面提取信息,但数据库的真正威力还在于用"关系"来综合多个数据表里面的记录,这种操作称之为"关联"或"结合"我们可以看到,select需要给出多个数据表里面的信息(不可重复);from需要知道从哪几个表里面做事;where则对几个表之间的关联信息作出详细的描述。
首先我们要学习最可靠的数据列引用方式:数据表名.数据列名。这样在查询中就一定不会混淆这个数据列到底在哪一个表里。
例子1:查询某一天内的学生们的考试成绩,用学号列出。
代码如下 | 复制代码 |
select scroe.student_id,event_date,score.score.event.type from event,score where event.date='2003-09-12' and event.event_id=score.event_id |
首先,利用event数据表把日期映射到一个考试事件编号,在利用这个编号把score表内相匹配的考试分数找出来。关联两个表,一个查询搞定。
例子2:查询某一天内的学生们的考试成绩,用姓名列出。
代码如下 | 复制代码 |
select student.name event.name,score.score,event.type form event,score,student where event.date='2003-09-12' and event.event_id= score.event_id and scroe.student_id=student.student_id; |
关联三个表,一个查询搞定。
例子3:查询一下缺席学生的名字,学号,缺席次数
代码如下 | 复制代码 |
select student.student_id,student_name count(absence.date) as absences from student,absence where student.student_id=absence.student_id //关联条件 group by student.student_id; |