《mysql必知必会》笔记1(检索、排序、过滤、计算、汇聚、分组)

一:了解SQL

        1:列是表中的字段,所有表都由一个或多个列组成的。行是表中的记录,表中的数据都按行存储。

        

        2:表中每一行都应该有可以唯一标识自己的一列或一组列。主键(一列或一组列),其值能够唯一区分每个行。虽然并不总是都需要主键,但应该是每个表都有一个主键。

        主键满足条件:任意两行不能有相同的主键值;每个行都必须具有一个主键值。

        可以使用多个列作为主键,所有列值的组合必须唯一(但单个列的值可以不唯一)。

 

        3:SQL是结构化查询语言,一种专门用来与数据库通信的语言。几乎所有的重要DBMS都支持SQL,但是事实上任意两个DBMS实现的SQL都不完全相同,本书的SQL专门针对mysql。

 

二:Mysql简介

        DBMS,数据库管理系统,Mysql就是一种DBMS。

        mysql命令,都以”;”结束。

 

三:使用mysql

        1:mysql使用之前,必须要登陆连接数据库。mysql在内部保存自己的用户列表,并且把每个用户和各种权限关联起来。

 

        2:最初连接数据库后,没有任何数据库打开,在执行任何数据库操作之前,必须要选择一个数据库。使用use关键字,eg:use test;


        3:   show databases;返回可用数据库的一个列表。

                  show tables;返回当前选择的数据库的所有表。

 

        4:   show columns from testtable; 或者describe testtable;返回表testtable的所有列的信息,比如:

 

        5:    show status;显示服务器状态信息;

                  show grants;   显示授予用户的安装权限;

                  show errors; show warnings; 显示服务器错误或警告信息。


四:检索数据

        1:每个sql语句都是由一个或多个关键字构成的。

        2:select语句,必须给出两条信息:选择什么,从什么地方选择,比如select cust_id from testtable; 得到的数据没有过滤,也没有排序。

        3:多条sql语句必须以分号分隔。sql语句不区分大小写。

 

        4:检索多个列,select后面给出多个列名,列名之间必须以逗号分隔,最后一个列名不加。比如:select cust_id, cust_name from testtable;

 

        5:distinct关键字,可以返回不同的值,比如select distinct cust_id from testtable; distinct关键字必须直接位于列名的前面,它应用于所有列而不仅是前置它的列。

 

        6:limit子句,返回限定数量的行。eg:select cust_id from testtable limit 5; 或 select cust_id from testtable limit 5,5; 返回从行5开始的5行。第一个数为开始位置,第二个数为行数。第一行为0.

 

五:排序检索数据

        1:检索出的数据顺序,可能是添加到表中的数据的顺序。但是如果不明确控制的话,不能依赖该排序顺序。

        2:order by子句,取一个列或多个列的名字,对输出进行排序。eg:select cust_name from testtable order by cust_name; 用非检索的列排序数据是完全合法的,eg:select cust_id from testtable order by cust_name;

        

        可以按多个列进行排序,列名之间用逗号分隔。多列排序时,按照循序进行,eg:select * from testtable order by cust_name, cust_id; 首先按照cust_name进行排序,如果有相同的cust_name的话,则按照cust_id排序,如下图:

         3:默认的排序为升序排序,可以用desc关键字指定降序排序,eg:select cust_id from testtable order by cust_id desc; desc关键字只能应用到直接位于其前面的列名,eg:select * from testtable order by cust_name desc, cust_id; 该语句只对cust_name列指定降序,而cust_id还是升序。

 

        4:再给出order by子句的时候,应该保证它位于from子句之后,如果使用limit,则必须位于order by之后。顺序不对会出错。

 

六:过滤数据

        1:在select语句中,数据根据where子句中指定的搜索条件,对数据进行过滤。where子句在表名(from子句)之后给出。eg;select cust_id, cust_name from testtable where cust_id = 1;

 

        2:如果同时使用order by和 where子句,应该让order by子句位于where之后。

 

        3:where子句支持的操作符有:

操 作 符

说  明

=

等于

<> 

不等于

!=

不等于

小于

<=

小于等于

大于

>=

大于等于

BETWEEN

在指定的两个值之间

IS NULL

为NULL值

 

        4:举例如下:

a:     select* from testtable where cust_id = 5;

b:     select* from testtable where cust_id < 5;

c:      select* from testtable where cust_name = 'john';      //单引号用来限定字符串,如果将值与串类型的列进行比较,则需要限定引号。用来与数值列进行比较的值不需要引号。所以,这里如果john不加引号的话,会出错。

d:      select* from testtable where cust_id between 1 and 3;     //使用between时,必须指定范围的两个值,这两个值必须用and关键字分隔。

 

        5:在一个列不包含值时,称其为包含空值NULL。NULL与包含0,空字符串不同。

        一个特殊的where子句,用来判断具有NULL值的列:is null;eg:select * from testtable where cust_city is null; 得到结果如下:


        注意:在匹配过滤和不匹配过滤时,并不返回NULL值的列,比如下面的语句,都不会返回任何数据:

mysql> select * from testtable where cust_city = NULL;     //” = null” 不等于 “is null”

Empty set (0.00 sec)


mysql> select * from testtable where cust_city != '1';

Empty set (0.00 sec)


mysql> select * from testtable where cust_city != '';

Empty set (0.00 sec)


mysql> select * from testtable where cust_city = '';

Empty set (0.00 sec)


七:数据过滤

        1:mysql允许给出多个where子句,多个where子句可以通过and或者or进行组合。eg:

        select * from testtable where cust_id < 5 and cust_name = ‘john’;

        select* from testtable where cust_id < 5 or cust_name = ‘john’;

 

         2:如果组合使用and和or,应该使用括号明确优先级,尽管默认情况下and具有比or更高的优先级。eg:

select * from testtable where (cust_id < 5 or cust_name = 'john') and cust_address is null;

 

        3:in操作符,可以指定或的关系。eg: select * from testtable where cust_id in (1,3);返回如下结果:

 

        注意:in操作符一般比or操作符更快。要注意in和between之间的区别。


        4:not操作符表示否定关系,eg:

select * from testtable where not cust_id >=5 order by cust_name;

 

八:用通配符进行过滤

        1:在搜索语句中使用通配符,必须使用like操作符,like指示mysql,后面的搜索模式利用通配符匹配,而不是直接相等匹配。

        2:mysql支持两种通配符,%表示任意字符出现任意次数;_匹配单个字符。eg:

select * from testtable where cust_name like '%i%';   //注意引号


 

select * from testtable where cust_name like '_i%';



        3:注意,通配符的搜索一般要比其他搜索花费更长的时间,所以不要过度使用通配符。

 

 

九:用正则表达式进行搜索

        1:mysql用where子句对正则表达式提供初步的支持,允许指定正则表达式过滤select检索出的数据。但是,mysql仅支持多数正则表达式实现的一个很小的子集。


        2:例如:select * from testtable where cust_name regexp ‘ik’;  regexp后跟的就是正则表达式。注意regexp和like的区别,如果上面的例子中,regexp换成like的话,则不会输出任何结果。因为like要求字段值完全匹配,尽管’mike’包含’ik’,但是like依然不会输出任何行。但是regexp仅仅要求包含即可。


        3:mysql中的正则表达式匹配不区分大小写,也就是上面的例子,可以这样写:

select* from testtable where cust_name regexp ‘IK’。如果需要区分,则可以使用binray关键字:select * from testtable where cust_name regexp binary ‘IK’。


        4:mysql支持的正则表达式:

|:或的关系,匹配其中之一;

[]:匹配其中的字符之一;

[a-z]:匹配a到z的任意字符;

*:0或多个匹配

+:1或多个匹配

?:0或1个匹配;

{n}:指定书目的匹配;

{n,}:不少于指定数目的匹配;

{n,m}:从n到m个匹配;

^:文本的开始

$:文本的结尾

[[:<:]]:词的开始

[[:>:]]:词的结尾

 

        5:mysql中的转义字符是\,比如,如果需要匹配”.”,则regexp “\.”

        6:可以在用带字符串的regexp来测试,比如:select ‘hello’ regexp ‘[0-9]’

 

十:创建计算字段

        1:有时,存储在表中的数据并不是应用程序直接需要的,需要直接从数据库中检索出转换、计算或格式化过的数据。这就是计算字段的作用。

          2:计算字段并不实际存在于数据表中,它是运行时在select语句内创建的。从应用程序的角度来看,计算字段与数据库中其他列的形式是一样的。只有数据库知道select语句中哪些列是实际的表列,哪些是计算字段。

          3:在sql语句中完成的转换和格式化工作,都可以直接在应用程序内完成。但一般来说,在数据库中完成这些操作要比在应用程序中完成要快很多。

 

          4:concat()函数可以实现字符串的拼接,eg:

select concat(cust_name, '(', cust_id, ')')from testtable;


 

        5:rtrim()函数,删除数据右侧多余的空格。eg:select rtrim(cust_name) from testtable;

        类似的,ltrim()函数,删除数据左侧多余的空格;trim()函数,删除串两边多余的空格。

 

        6:计算字段默认没有名字,可以使用别名。这样在应用程序中就可以引用它了。别名使用as关键字。eg:  

select concat(cust_name, '(', cust_id, ')')  as cust_nameid from testtable;


 

        这样,任何应用程序都可以按cust_nameid这个别名引用这个列,就像它是一个实际的表列一样。

 

        7:计算字段,还可以对检索出的数据进行数学运算,比如:select cust_id * 2 from testtable;

        

        可以得到所有cust_id 乘以2之后的值。mysql支持的算术操作有:+, -, *, /。

 

        8:select语句,可以省略from子句,来测试和实验函数。比如:select 3*2; 将返回6. select trim(‘ abc ’); 将返回’abc’。

 

十一:使用数据处理函数

        1:sql支持利用函数来处理数据。但是函数的可移植性不强,这点要注意。

          2:大多数sql实现支持以下类型的函数:处理字符串的函数;处理数值的函数;处理日期和时间的函数;返回DBMS信息的函数。

        

          3:upper(),将文本转换为大写。比如:select upper(cust_name) as nocasename from testtable;


 

        其他的文本处理函数有:left(), length(), locate(), lower(), ltrim(), right(), rtrim(), substring(), upper(), soundex()等。可以使用help函数名,查看函数用法,比如:help left;

        4:mysql中,日期和时间,采用特殊的格式存储,以便能够快速和有效的排序或过滤,并节省内存。在应用程序中,一般都要使用日期和时间函数来对数据库中的日期时间进行处理。

 

        5:mysql使用的日期格式,不管是插入或更新表值,还是使用where子句进行过滤,日期必须为yyyy-mm-dd格式。比如:select * from testtable where cust_date = '2014-10-01 10:21:34';


 

        虽然其他的日期格式可能也行,但是这是首选的日期格式,因为它排除了多义性。


        6:日期时间格式的数据,包含日期和时间。date()函数,可以从日期时间格式的数据中,提取出日期。比如:

select * from testtable where date(cust_date) = '2014-12-01';


 

        其他的日期时间处理函数:adddate(), addtime(),curdate(), curtime(), date(), datediff(), date_add(), date_format(), day(),dayofweek(), hour(), minute(), month(), now(), second(), time(), year()。

 

        7:数值处理函数,这些函数一般用于代数,三角或几何运算。因此没有字符处理或日期时间处理函数使用那么频繁。常用的数值处理函数有:abs(), cos()等。

 

十二:汇总数据

        1:mysql提供了汇总数据的函数,比如统计行数,计算最大值,最小值,平均值等。

          2:avg()函数计算某列的平均值。比如:select avg(cust_num) from testtable;


 

          avg还可以计算特定行的平均值,比如:select avg(cust_num) from testtable where cust_name = ‘john’;


 

          avg函数只能确定单个列的平均值;avg函数忽略列值为NULL的行。

 

        3:count()函数,统计行数。它有两种使用方式:

        count(*) 对行数进行统计,不管列中包含的是空值NULL,还是非空值;

        count(column)对特定列中具有值的行进行统计,忽略NULL值的行。

 

        比如:select count(*) from testtable;返回 9;

        select count(*) from testtable where cust_name = 'john';返回2;

        select count(cust_name) from testtable where cust_name ='john';返回2;

        select count(cust_email) from testtable ;返回0.

 

        4:max()函数,返回指定列中的最大值,max必须指定列名,比如:

        select max(cust_num) from testtable;返回98

        select max(cust_num) from testtable where cust_name = 'john';返回98

        select max(cust_num) from testtable where cust_name = 'tom';返回34

 

        max函数也可以用在时间日期格式,或者字符串上。比如:


 


        max函数忽略值为NULL的行

        min函数返回最小值,与max相反,不再赘述。

 

        5:sum()函数,用来返回指定列值的和。比如:

select sum(cust_num) from testtable; 返回359

select sum(cust_num) from testtable where cust_name = 'john';  返回152

         sum忽略NULL值的列。

 

        6:distinct关键字,可以只对具有不同值行进行计算。它只适用于mysql 5及以后版本。all关键字是它的反义,不过all是默认的,所以可以不加。

        比如:select avg(distinctcust_num) from testtable; 返回43.3750

select sum(distinct cust_num) from testtable; 返回347

select count(distinct cust_name) from testtable; 返回5

        可见加了distinct关键字之后,返回结果的不同。注意,distinct 不能用于count(*),也就是不能count(distinct  *),会出错。

 

        7:组合使用,比如:

select count(*) as cust_count,

    min(cust_num) as cust_minnum, max(cust_num) as cust_maxnum,

         avg(cust_num) as cust_avgnum from testtable;

 

十三:分组数据

        1:目前为止,所有的计算都是在表的所有数据或匹配特定的where子句的数据上进行的,比如:select count(*) as num_pords from products where vend_id = 1003;  products表是产品表,每行一个产品,该表中记录了产品ID,供应商ID,产品名,价格,描述等信息,如下:


 

        上面那句sql语句,就是在该表中,查询供应商1003所供应产品的总数。

          但是,如果需要返回所有供应商提供的产品数怎么办?此时需要分组,分组允许把数据分为多个逻辑组,以便能够对每个组进行聚集计算。

 

          2:分组通过select语句中的group by子句建立。比如:select vend_id, count(*) as num_prods from products group by  vend_id; 该语句返回结果如下:


 

        group by子句,指示mysql分组数据,然后对每个组而不是整个结果集进行聚集运算。所以上面的例子中,group by子句指示mysql按vend_id排序并分组数据,因而count(*)是针对每个分组进行计算。

 

          3:除了聚集计算之外,select语句中的每个列都必须在group by子句中给出;如果分组列中具有NULL值,则NULL将作为一个分组返回,如果列中有多行NULL值,它们将分为一组。

          4:group by必须在where子句之后,order by子句之前。

 

          5:mysql允许过滤分组,规定包括哪些分组,排除哪些分组。但是因为where没有分组的概念,where过滤的是行而不是分组,所以,提供了having子句。

          having子句非常类似于where,它们的句法是相同的,只是关键字有差别。

 

          6:比如:

select cust_id, count(*) as orders from orders group by cust_id having count(*) >=2;

         orders表存储顾客订单。每个订单具有订单号,订单日期,订单顾客id信息。如下:


 

        所以,上面的sql语句,返回订单数超过2个的客户id,结果如下:


        7:where是在分组前进行过滤,having是在分组后进行过滤。where排除的行不包括在分组中。下面是一个组合使用where和having的例子:

        select vend_id, count(*) as num_prods from products where prod_price >= 10 group by vend_id having count(*) >= 2;

        该语句返回具有2个以上,并且价格在10以上的产品的供应商。结果如下:


 

          上面的语句,首先通过where prod_price >= 10对整体数据进行过滤,然后在过滤的基础上,找到提供两个产品以上的供应商ID。执行的顺序就是:首先where过滤,然后通过vend_id进行分组,然后having进行分组过滤。

 

          8:虽然group by分组的数据可能以分组顺序给出,但不能保证情况总是这样,因为这不是sql规范要求的。所以,如果需要按序输出,则应该提供明确的order by语句。比如:

        select order_num, sum(quantity * item_price) as ordertotal from orderitems group by order_num  having  sum(quantity *item_price) >= 50;

          orderitmes表存储每个订单的实际物品,每个订单的每个物品站一行,其中记录了订单号,订单物品,物品数量,物品价格等。如下:


 

        所以,上面的sql语句,返回,所有订单总价超过50的订单,结果如下:


 

        如果需要按照总价排序,可以这样:

select order_num, sum(quantity*item_price) as ordertotal from orderitems group by order_num having sum(quantity*item_price) >= 50 order by ordertotal; 结果如下:

 

        9:迄今为止,所有的子句顺序如下:

子句

说明

是否必须使用

SELECT

要返回的列或表达式

FROM

从中检索数据的表

仅在从表选择数据时使用

WHERE

行级过滤

GROUP BY

分组说明

仅在按组计算聚集时使用

HAVING

组级过滤

ORDER BY

输出排序顺序


原文地址:https://www.cnblogs.com/gqtcgq/p/7247270.html