• 《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

    输出排序顺序


  • 相关阅读:
    lines-HDU5124(区间处理 +离散化)
    Reorder the Books-HDU5500
    Bad Hair Day-POJ3250(简单的入栈出栈)
    Count the Colors-ZOJ1610(线段树区间求)
    Just a Hook-HDU1698(线段树求区间)
    Mayor's posters-POJ2528(线段树+离散化)
    A Simple Problem with Integers-POJ3468
    Strongly connected-HDU4635
    Caocao's Bridges-HDU4738(Tarjin+求桥)
    Warm up-HUD4612(树的直径+Tarjin缩点)
  • 原文地址:https://www.cnblogs.com/gqtcgq/p/7247270.html
Copyright © 2020-2023  润新知