乘风原创程序

  • SQL考点之SQL查询、SQL支持数据类型
  • 2020/10/8 14:31:45
  • 如题:2019年10月

    除前两问是涉及关系代数的内容外,其他都是SQL的查询的考察,足见这部分的重要性。

    其实是完成了下面的复习后,再来填的答案:

    26、看到“女”这个条件,应该想到是选择。所以是?σ性别=女(采购)

    27、商品名,生产日期是属性,所以是投影。π商品名,生产日期(商品)

    28、应该是可以想到between ...and

    select 商品编号
    from 商品
    where 价格 between 10 and 15;
    

    29.分析:查询的是商品编号、采购日期、采购数量,属于采购这个关系

    ? ? ? ? ? ? ? 条件:刘聪,采购员姓名,属于采购员这个关系,到这里,基本就可以得出,两个关系是通过“编号”这个外键联系起来的。

    题目要求用(嵌套查询),也就是子查询实现。子查询,要实现的就是“外表”的返回‘编号’,主查询,查询“内表”的编号对应的要返回的内容。所以:

    select 商品编号,采购日期,采购数量
    from 采购
    where 编号 in (select 编号 from 采购员 where 姓名=‘刘聪’);

    ? ? ?30.分析:编号、商品编号、采购日期,都属于采购这个关系,那么采购可以当作视图的基表

    条件是采购数量大于100,这个其实是基表的条件。还有一点就是视图的语法:

    create view VSC 商品编号,编号,采购日期
    as
    select 商品编号,编号,采购日期
    from 采购
    where 采购数量 > 100;

    1、 SQL的作用?

    其实是用户操作关系型数据库的接口语言。SQL语句用于取回和更新数据库中的数据。

    每一种数据库有自己版本的SQL语言,但是为了与ANSI标准相兼容,SQL必须以相似的方式共同地来支持一些主要的关键词(比如 SELECT、UPDATE、DELETE、INSERT、WHERE等等)。
    除了SQL标准之外,大部分SQL数据库程序都拥有自己的私有扩展。

    2、SQL语句,

    总体分类?详见《数据库考点之SQL语句(数据库、表、索引、视图)》,不再重复了,单列查询部分

    3、mysql之查询功能:

    DQL:Data Query Language是SQL语言的核心功能
    用于查询数据库对象中所包含的数据,能够进行单表查询、连接查询、嵌套查询,以及集合查询等各种复杂程度不同的数据库查询,并将数据返回到客户机中显示。其数学理论基础是关系代数中的选择、投影、连接。

    4、单表查询

    select语法:

    select
    [all | distinct |distinctrow]
    select_expr [,select_expr ...]
    from table_references
    [where where_condition]
    [group by {col_name | expr | position}
     [asc | desc],...[with rollup]]
    [having where_condition]
    [order by {col_name | expr | potin}
     [asc | desc],...]
    [limit {[offset,]row_count | row_count offset offset}]
    

    注:只有 select? ?from是必须的,其他都是可选的。并且其他可选项都要按照语法顺序所使用。

    distinct:不同,含义为:指定是否返回结果集中重复的行。与distinct row同义,指向select语句中指定的所有的列,而不仅仅是前置的某个列。

    那么有没有什么记忆技巧呢?

    首先,如果给我们一张表,我们是从(from)这张表开始查,然后如果需要过滤就(where)过滤,之后如果引用了聚合函数,就需要进行分组(group by),接下来如果我们需要对这前面阶段–分组得到的结果进行二次过滤的时候,就用到(having)进行过滤,只要记住,having只服务于group by就行了,经过这么多步骤得出来的结果后我们选择(select)哪些需要显示的用什么顺(order by )显示出来,如果是mysql 数据库,最后还可以加个限制(limit)取出来的条数。

    通过这些关键词,可以知道个大概操作数据库的逻辑表示顺序。下面分别展开说明:

    • 从表中查询指定的列(SELECT)
    SELECT product_id, product_name, purchase_price
      FROM Product;
    

    select select_expr,可进行数据库所支持的任何运算。

    • 查询出所有的列
    SELECT *
      FROM Product;

    ?

    • 为列设定别名(AS)

    为字段取别名
    MySQL可以指定列别名,替换字段或表达式。
    列名 [AS] 列别名

    select studentid as 学号,sname as 姓名,sex as 性别 from TStudent
    select studentid 学号,sname 姓名,sex 性别 from TStudent

    为表取别名
    为了方便操作或者需要多次使用相同的表时,可以为表指定别名,用别名替代表原来的名称。
    表名 [AS] 表别名

    select a.studentid 学号,a.sname 姓名,a.sex 性别 from TStudent as a;
    select a.studentid 学号,a.sname 姓名,a.sex 性别 from TStudent a;

    再比如:?

    SELECT product_id AS id,
           product_name AS name,
           purchase_price AS “价格”
      FROM Product;

    ?

    • 将查询出的一列指定为常数
    SELECT ‘2009-02-24’ AS date, product_id, product_name
      FROM Product;

    ?

    • 从查询结果中删除重复行(DISTINCT)

    在SELECT语句中可以使用DISTINCE关键字指示MySQL消除重复的记录值。
    SELECT DISTINCT 字段名 FROM 表名;

    SELECT DISTINCT product_type
      FROM Product;

    ?

    • 指定查询的条件(WHERE)
    SELECT product_name, product_type
      FROM Product;
     WHERE product_type = '衣服';
    • 替换查询结果集中的数据使用case

    语法:

    select select_expr
    case
    when 条件1 then 表达式1
     when 条件2 then 表达式2
    ...
    else 表达式
    end [as]column_alias

    如:查询表custormers中客户的cust_name和cust_sex,判断结果集中cust_sex列,若为‘M’则输出‘男’,否则输出‘女’,同时将cust_sex列显示为“性别”

    select cust_name,
    case
     when cust_sex = 'M' as '男'
     else '女'
     end as '性别'
    form mysql_test.customers;

    再比如:?

    SELECT product_name,
           CASE WHEN product_type = '衣服'
                THEN CONCAT('A:', product_type)
                WHEN product_type = '办公用品'
                THEN CONCAT('B:', product_type)
                WHEN product_type = '厨房用具'
                THEN CONCAT('C:',product_type)
                ELSE NULL
           END AS abc_product_type
      FROM Product;

    ?

    • 带IN关键字的查询

    查询满足指定范围内的条件(其实是一个枚举表)的记录,使用IN操作符,将所有检索条件用括号括起来,检索条件用逗号分隔开,只要满足条件范围内的一个值即为匹配项。
    查新姓 王 刘 石的学生

    select * from TStudent where left(sname,1) in ('王','刘','石');

    再比如:

    SELECT product_name, purchase_price
      FROM Product
     WHERE purchase_price IN (320, 500, 5000);

    ?也可以用NOT IN

    SELECT product_name, purchase_price
      FROM Product
     WHERE purchase_price NOT IN (320, 500, 5000);

    注意:在使用IN 和NOT IN 时是无法选取出NULL 数据的。?

    使用子查询作为IN谓词的参数:

    SELECT product_name, sale_price
      FROM Product
     WHERE product_id IN (SELECT product_id
                             FROM ShopProduct
                            WHERE shop_id = '000C');

    注:子查询,也就是所说的“嵌套”,题四问,就是要求用嵌套来实现

    mysql区分四类子查询:

    使用in子查询:这里的子查询只返回一列数据,数据列里的值将提供给外层查询语句进行比较操作。

    语法:?expression [not] in (subquery)

    subquery:指子查询

    expression:用于指定表达式,当表达式与子查询中返回的结果集中的某个值相等时,会返回true,否则返回false.

    如:查询成绩高于80的学生的学号与姓名?

    select studentNo,studentName
    from tb_student
    where studentNo in (select studentNo from tb_score where score>80);

    ?

    使用比较运算符子查询,将表达式的值与子查询结果进行比较运算

    语法:

    expression {= | < | <= | > | >= | <=> | <> | !=} {all | some | any}(subquery)

    all,some,any:用于指定对比较运算的限制,all指对结果每个值都进行比较,都满足关系时会返回true

    som,any是同义词,表示只要与结果的某个值相等就返回true.

    如:

    select from TStudent 
    where studentid=any (select distinct studentid from TScore where mark>98);

    等价于:

    select from TStudent 
    where studentid in (select distinct studentid from TScore where mark>98);

    再比如:子查询查出考试成绩大于98的学生的studentid

    select from TStudent 
    where studentid>some (select distinct studentid from TScore where mark>98)

    使用exist的子查询,主要判断子查询结果集是否为空

    系统对子查询进行运算以判断子查询是否返回行,如果至少返回一行,那么EXISTS的结果为true,此时外层查询语句将进行查询;如果子查询没有返回任何行,那么EXISTS返回的结果是false,此时外层语句将不进行查询。

    语法:

    exist (subquery) --不为空返回true,如:

    SELECT product_name, sale_price
      FROM Product AS P 
     WHERE EXISTS (SELECT *
                      FROM ShopProduct AS SP 
                     WHERE SP.shop_id = '000C'
                       AND SP.product_id = P.product_id);

    再比如:查询学号为01001同学信息,还有成绩。

    select from TStudent 
    where studentid='01001' 
    and exists (select from TScore where studentid='01001');

    ?

    • 带BETWEEN AND的范围查询

    查询某个范围内的值,该操作符需要两个参数,即范围的开始值和结束值,如果字段值满足指定的范围查询条件,则这些记录被返回。
    以下查询条件,查询学号100到150的学生,包括100和150
    select?from TStudent where convert(studentid,signed) between 100 and 150
    等价于

    select?from TStudent where convert(studentid,signed)>=100
    and convert(studentid,signed)<=150

    自动转换类型

    select * from TStudent where studentid between 100 and 150
    • 带LIKE的字符匹配查询

    百分号通配符‘%’,匹配任意长度的字符,甚至包括零字符
    下划线通配符‘_’,一次只能匹配任意一个字符
    查找姓名中间字为“志”字的学生

    select?from TStudent where sname like '志' ;

    查找姓名中有“志”字的学生

    select?from TStudent where sname like '%志%';

    前方一致查询:

    SELECT *
      FROM SampleLike
     WHERE strcol LIKE 'ddd%';

    也可用_(下划线)代替%,但_只能代表一个字符

    SELECT *
    FROM SampleLike
    WHERE strcol LIKE 'abc_';

    ?

    中间一致查询:

    SELECT *
      FROM SampleLike
     WHERE strcol LIKE '%ddd%';

    ?

    后方一致查询:

    SELECT *
      FROM SampleLike
     WHERE strcol LIKE '%ddd';

    ?

    • 查询空值

    在SELECT语句中使用IS NULL子句,可以查询某字段内容为空记录。

    为了选取出某些值为NULL 的列的数据,不能使用=,而只能使用特定的谓词IS NULL

    语法:

    expressions is [not] null
    ?SELECT product_name, purchase_price
      FROM Product
     WHERE purchase_price IS NULL;


    查找邮箱是空值的记录

    select * from s where email is null;
    • ?带AND的多条件查询

    使用AND连接两个甚至多个查询条件,多个条件表达式之间用AND分开。

    select * from TStudent where sex='男' and Class='net' and studentid&gt;20 and studentid&lt;50;
    • 带OR的多条件查询

    OR操作符,表示只需要满足其中一个条件的记录即可返回。OR也可以连接两个甚至多个查询条件,多个条件表达式之间用AND分开。

    select * from TStudent where sname like '%志%' or class='net';
    • 用LIMIT限制查询结果的数量

    语法:

    limit {[offset,] row_count | row_count offset offset}

    offset:可选项,默认数字为0,指定第一行在查询结果中的位置(从哪个列开始输出)。

    row_count:返回数据的行数。

    row_count 关键字offset offset:从第offset+1行开始,取row_countt行。

    LIMIT关键字可以返回指定位置的记录。
    LIMIT [位置偏移量,] 行数
    返回前10个学生

    select?from TStudent limit 10;

    返回第11-20个学生,偏移量是10,就意味着从第11个开始取10条记录。

    select?from TStudent limit 10,10;

    再比如:

    select *
    from user
    where username='xiaomin'
    order by user_id DESC?
    limit 1 offset 2 或者 limit 2,1
    
    
    'order by user_id DESC' :根据 user_id 倒序排列。如果没有 DESC 表示正序排列 ?
    'limit' : 设定返回的记录数 ?
    'offset' : 设定查询时偏移个数,默认为0。

    ?难点

    问题:

    LIMIT 2,1
    LIMIT 1 OFFSET 2
    
    这两个语句为什么表达的意思是一样的呢?

    解答:

    记住三点:
    1.在计算机中索引都是从0开始的。但是LIMIT、OFFSET后面的数字只表示个数,和索引没有关系。
    2.一般涉及到偏移参数(偏移3行),这样的描述都不包含所描述的那个个数,即3行数据已经不在“视野”内,偏移到“视野外”了,看不见,自然就不包含了。
    3.一般涉及到索引参数(截取索引3到索引5),这样的描述包含索引2,不包含索引5
    
    LIMIT 2,1 : 表示偏移2行数据,获取1个数据。即获取的是第3行数据
    LIMIT 1 OFFSET 2 : 表示获取1个数据,但是偏移2行数据,即获取的也是第3行数据
    • 使用正则表达式查询

    正则表达式作用是匹配文本,将一个模式(正则表达式)与一个文本串进行比较。MySQL用WHERE子句对正则表达式提供了初步的支持,允许指定用正则表达式过滤SELECT检索出的数据。
    在SQL查询语句中,查询条件REGEXP后所跟的东西作为正则表达式处理。

    查询以特定字符或字符串开头的记录

    字符‘^’匹配以特定字符或者字符串开头的文本。

    select * from TStudent where sname regexp '^刘平';

    查询以特定字符或字符串结尾的记录

    字符‘$’匹配以特定字符或者字符串结尾的文本。

    select * from TStudent where cardid regexp '36$';

    用符号"."来替代字符串中的任意一个字符

    字符‘.’匹配任意一个字符。

    select * from TStudent where sname regexp '.康.';

    使用"*"和"+"来匹配多个字符

    星号‘’匹配前面的字符任意多次,包括0次。
    加号‘+’匹配前面的字符至少一次。
    找出×××以19开始,以6结束的学生

    select?from TStudent where cardid regexp '^19.6$'

    找出×××号中有123的学生

    select?from TStudent where cardid regexp '.123+.';

    匹配指定字符串

    正则表达式可以匹配指定字符串,只要匹配字符串在查询文本中即可,如要匹配多个字符串,多个字符串之间使用分隔符‘|’隔开。

    select * from TStudent where sname regexp '武|尹|罗';

    匹配指定字符中的任意一个

    方括号“[]”指定一个字符集合,只匹配其中任何一个字符,即为所查找的文本。不支持汉字。

    select?from TStudent where email regexp '[w-z]';
    select?from TStudent where cardid regexp '^[1-3,7]';

    匹配指定字符以外的字符

    “[^字符集合]”匹配不在指定集合中的任何字符。

    select * from TStudent where cardid regexp '^[^1-7]';

    使用{M}或者{M,N}来指定字符串连续出现的次数

    “字符串{n,}”表示至少匹配n次前面的字符。“字符串{n,m}”表示匹配前面的字符串不少于n次,不多于m次。
    查找×××中出现138并且后面有8位0-9的数字的学生。

    select * from TStudent where cardid regexp '138[0-9]{15}';
    • 合并查询结果

    利用UNION关键字,可以给出多条SELECT语句,并将它们的结果组合成单个结果集。合并时,两个表对应的列数和数据类型必须相同。各个SELECT语句之间使用UNION(联盟)或UNION ALL关键字分隔。
    要求第一个SQL语句返回的列和第二条返回的列数相同,

    select studentid,sname from TStudent where studentid<=10
    union
    select studentid, sname from TStudent where sname like '王%';

    ?

    • 对表进行分组(GROUP BY)

    作用为:将结果集中的数据行按照列的值进行逻辑分组,指示对分组进行操作,而不再是整个结果集。

    语法:

    group by {col_name | expr | position }[asc|desc],... [with rollup]

    ?col_name:r指定选择分组的列,列必须是select选择中的列

    expr:用于分组表达式,通常与聚合函数一块使用,如下用count(*)

    position:选择列在结果集中的位置。

    rollup:卷起,with rollup:可得到每个分组及整体的汇总行

    SELECT product_type, COUNT(*)
      FROM Product
     GROUP BY product_type;

    再如:在customers中获取包含相同地址的男性客户数和女性客户人数:

    select cus_addr,cus_sex,count(*) as '人数'
    from mysql_test.customers
    group by cus_addr,cus_sex;

    ?如要求获得相同地址的男性客户数、女性客户数、总客户数、总人数:只要在以上SQL语句,加上with rollup

    having:过滤分组:规则包含哪些分组,排除哪些分组

    语法:

    having where_condition

    注:聚合函数只能出现在SELECT列表、HAVING子句和ORDER BY子句中

    例如:

    查找,列出相同地址的客户人数少于3的所有的客户姓名及对应的地址

    select cus_name,cus_addr
    from mysql_test.customers
    group by cus_addr,cus_name
    having count(*)<=3;

    再比如:查询平局分大于80的学生

    select concat(a.StudentID,' ',a.sname) ss,avg(b.mark) m 
    from TStudent a join TScore b 
    on a.StudentID=b.StudentID 
    group by ss having m>80;

    使用聚合函数查询例子:

    COUNT()函数

    select class,COUNT(*) from?TStudent?group by class;

    SUM()函数
    查询每个学生总分

    select concat(a.StudentID,' ',a.sname) ss,SUM(b.mark) 
    from?TStudent?a join TScore b on a.StudentID=b.StudentID?
    group by ss;

    AVG()函数

    统计每个班平均分

    Select class,AVG(mark) 
    from?TStudent?a join TScore b on a.StudentID=b.StudentID?
    group by class;

    多字段分组

    统计每班每科平均分,需要按两列分组class和subJectName

    select class,subJectName,AVG(mark) 
    from TStudent a join TScore b on a.StudentID=b.StudentID 
    join TSubject c on b.subJectID=c.subJectID 
    group by class,subJectName;

    GROUP BY和WHERE并用时SELECT语句的执行顺序:

    FROM → WHERE → GROUP BY → SELECT

    SELECT purchase_price, COUNT(*)
      FROM Product
     WHERE product_type = '衣服'
     GROUP BY purchase_price;

    ?

    • 对查询结果进行排序(ORDER BY)

    语法:

    order by  {col_name | expr | position }[asc|desc],... 

    含义与group by 后相同,不再重复。

    不同点:

    例如:查找平均分大于80分,按平均分排序。

    select concat(a.StudentID,' ',a.sname) ss,avg(b.mark) m 
    from TStudent a join TScore b 
    on a.StudentID=b.StudentID 
    group by ss having m>80 order by m;

    ?再如书上例子:在customers表中,按照姓名和地址降序排列,输出客户姓名和性别

    select cus_name,cus_sex
    from mysql.customers
    order by cus_name desc,cus_addr desc;

    子句的书写顺序

    SELECT → FROM → WHERE → GROUP BY → HAVING → ORDER BY

    SELECT product_id, product_name, sale_price, purchase_price
      FROM Product
    ORDER BY sale_price;

    ?

    • 升序(ASC)或降序(DESC)
    SELECT product_id, product_name, sale_price, purchase_price
      FROM Product
    ORDER BY sale_price DESC;

    注意:默认升序

    ?

    算数运算符和比较运算符

    • 算数运算符

    加 +

    减 -

    乘 *

    除 /

    注意:所有包含NULL 的计算,结果肯定是NULL。

    SELECT product_name, sale_price, sale_price * 2 AS "sale_price_x2"
      FROM Product;

    ?

    • 比较运算符

    等于 =

    不等于 <>

    大于 >

    大于等于 >=

    小于 <

    小于等于 <=

    SELECT product_name, product_type, regist_date
      FROM Product
     WHERE regist_date < '2009-09-27';

    ?

    • 将算数运算符和比较运算符结合使用:
    SELECT product_name, sale_price, purchase_price
      FROM Product
     WHERE sale_price - purchase_price >= 500;
    

    ?

    注意:不能对NULL使用比较运算符,正确的方法是:

    SELECT product_name, purchase_price
      FROM Product
     WHERE purchase_price IS NULL;
    

    ?

    逻辑运算符(NOT、AND、OR)

    • NOT
    SELECT product_name, product_type, sale_price
    FROM Product
    WHERE NOT sale_price >= 1000; 

    (也就是sale_price<1000)

    ?

    • AND

    AND运算符在其两侧的查询条件都成立时整个查询条件才成立,其意思相当于“并且”。

    SELECT product_name, purchase_price
      FROM Product
     WHERE product_type = '厨房用具'
       AND sale_price >= 3000;
    

    ?

    • OR

    运算符在其两侧的查询条件有一个成立时整个查询条件都成立,其意思相当于“或者”。

    SELECT product_name, purchase_price
      FROM Product
     WHERE product_type = '厨房用具'
       OR sale_price >= 3000;

    ?

    对表进行聚合查询

    常用的五个聚合函数:

    • COUNT: 计算表中的记录数(行数)
    • SUM: 计算表中数值列中数据的合计值
    • AVG: 计算表中数值列中数据的平均值
    • MAX: 求出表中任意列中数据的最大值
    • MIN: 求出表中任意列中数据的最小值

    ?

    • 计算全部数据的行数(包含NULL)
    SELECT COUNT(*)
      FROM Product;

    ?

    • 计算某一列的行数(不包含NULL)
    SELECT COUNT(purchase_price)
      FROM Product;

    ?

    • 计算删除重复数据后的行数
    SELECT COUNT(DISTINCT product_type)
      FROM Product;

    (所有的聚合函数都可以使用DISTINCT)

    ?

    • SUM/AVG函数只能对数值类型的列使用,而MAX/MIN函数原则上可以适用于任何数据类型的列
    SELECT MAX(regist_date), MIN(regist_date)
      FROM Product;

    5、多表连接(是以列为单位进行的),才是关系型数据库最主要的查询

    内连接查询,最常用的连接类型。内连接也是默认的表连接。

    内连接(INNER JOIN)使用比较运算符根据每个表共有的列的值匹配两个表中的行,并列出表中与连接条件相匹配的数据行,组合成新的记录。在内连接查询中,只有满足条件的记录才能出现在结果关系中。

    语法:

    select some_columns
    from table1 
    inner join 
         table2 
    on some_conditions;

    some_columns:用于指定需要检索的列名。

    some_conditions:两张表按什么条件进行连接。[<table1>]<列名><比较运算符>[<table2>]<列名>

    隐式的内连接,没有INNER JOIN,形成的中间表为两个表的笛卡尔积。

    select a.StudentID, a.Sname, b.mark from TStudent a, TScore b 
    where a.StudentID=b.StudentID;

    显示的内连接,一般称为内连接,有INNER JOIN,形成的中间表为两个表经过ON条件过滤后的笛卡尔积。

    select a.StudentID, a.Sname, b.mark 
    from TStudent a inner join TScore b 
    on a.StudentID=b.StudentID;
    
    select a.StudentID,a.Sname,c.subJectName,b.mark 
    from TStudent a join TScore b 
    on a.StudentID=b.StudentID join TSubject c 
    on b.subJectID=c.subJectID;

    效果:

    MySQL数据库基础(五)——SQL查询

    如果某列只在一张表中,就可以不用指明是哪个表中的列。

    select a.StudentID,a.Sname,subJectName,mark 
    from TStudent a join TScore b on a.StudentID=b.StudentID 
    join TSubject c on b.subJectID=c.subJectID;

    再比如:使用等值连接

    SELECT SP.shop_id, SP.shop_name, SP.product_id, P.product_name, P.sale_price
      FROM ShopProduct AS SP INNER JOIN Product AS P 
        ON SP.product_id = P.product_id;

    像这样使用联结运算将满足相同规则的表联结起来时,WHERE、GROUP BY、HAVING、ORDER BY 等工具都可以正常使用.

    再比如:

    连接两张表,只返回满足条件的数据。

    user 表和 permission表:

    select user.name , permission.type from user
    join permission on permission.id = user.id

    外连接查询?

    外连接分为左连接、右连接、全连接。外连不但返回符合连接和查询条件的数据行,还返回不符合条件的一些行。外连接分三类:左外连接(LEFT OUTER JOIN)、右外连接(RIGHT OUTER JOIN)和全外连接(FULL OUTER JOIN)。

    三者的共同点是都返回符合连接条件和查询条件(即:内连接)的数据行。不同点如下:
    左外连接还返回左表中不符合连接条件单符合查询条件的数据行。
    右外连接还返回右表中不符合连接条件单符合查询条件的数据行。
    全外连接还返回左表中不符合连接条件单符合查询条件的数据行,并且还返回右表中不符合连接条件单符合查询条件的数据行。全外连接实际是上左外连接和右外连接的数学合集(去掉重复),即“全外=左外 UNION 右外”。

    左连接
    包含左边表的全部行(不管右边的表中是否存在与它们匹配的行),以及右边表中全部匹配的行。
    左连接的结果集包括?LEFT OUTER子句中指定的左表的所有行,而不仅仅是连接列所匹配的行。如果左表的某行在右表中没有匹配行,则在相关联的结果集行中右表的所有选择列表列均为空值。?

    select a.StudentID, a.Sname, b.mark from TStudent a left join TScore b on a.StudentID=b.StudentID;

    MySQL数据库基础(五)——SQL查询

    再比如:

    user 表和 permission表:

    select user.name , permission.type from user
    left join permission on permission.id = user.id

    两个表:

    SELECT SP.shop_id, SP.shop_name, SP.product_id, P.product_name, P.sale_price
      FROM ShopProduct AS SP LEFT OUTER JOIN Product AS P ①
        ON SP.product_id = P.product_id;

    三个以上表:

    SELECT SP.shop_id, SP.shop_name, SP.product_id, P.product_name, P.sale_price, IP.inventory_quantity
      FROM ShopProduct AS SP INNER JOIN Product AS P ①
        ON SP.product_id = P.product_id
              INNER JOIN InventoryProduct AS IP ②
                 ON SP.product_id = IP.product_id
     WHERE IP.inventory_id = 'P001';

    右连接:
    右连接包含右边表的全部行(不管左边的表中是否存在与它们匹配的行),以及左边表中全部匹配的行。
    右连接是左连接的反向连接。将返回右表的所有行。如果右表的某行在左表中没有匹配行,则将为左表返回空值。????

    select a.StudentID, a.Sname, b.mark from TScore b right join TStudent a on a.StudentID=b.StudentID;

    MySQL数据库基础(五)——SQL查询

    全连接:
    全连接返回左表和右表中的所有行。当某行在另一个表中没有匹配行时,则另一个表的选择列表列包含空值。如果表之间有匹配行,则整个结果集行包含基表的数据值。MySQL不支持全外连接。可以通过左外和右外求合集来获取全外连接的查询结果。

    select a.StudentID, a.Sname, b.mark from TStudent a left join
    TScore b on a.StudentID=b.StudentID
    union
    select b.StudentID, c.subJectName, b.mark from TScore b right join
    TSubject c on b.subJectID=c.subJectID;

    MySQL数据库基础(五)——SQL查询

    交叉连接

    交叉连接返回左表中的所有行,左表中的每一行与右表中的所有行组合。交叉连接有显式的和隐式的,不带ON子句,返回的是两表的乘积,也叫笛卡尔积。
    FROM子句中的表或视图可通过内连接或全连接按任意顺序指定;但是,用左或右向外连接指定表或视图时,表或视图的顺序很重要。

    隐式交叉连接,没有cross join

    select a.StudentID, a.Sname, b.mark from TStudent a,TScore b where a.StudentID < 4;

    显示交叉连接,有cross join

    select a.StudentID, a.Sname, b.mark from TStudent a cross join TScore b where a.StudentID < 4;

    MySQL数据库基础(五)——SQL查询

    ?

    表的加减法

    • 表的加法(UNION)
    SELECT product_id, product_name
       FROM Product
    UNION
    SELECT product_id, product_name
      FROM Product2;

    通过UNION 进行并集运算时可以使用任何形式的SELECT 语句,WHERE、GROUP BY、HAVING 等子句都可以使用,但是ORDER BY 只能在最后使用一次。

    注意:UNION会删去两个表中的重复记录。如果想保留重复记录,可以在UNION后面加ALL

    • 选取表中的公共部分(INTERSECT)

    MySQL不支持INTERSECT

    • 表的减法(EXCEPT)

    MySQL不支持EXCEPT

    ?

    扩展:

    SQL查询的原理

    第一、单表查询:根据WHERE条件过滤表中的记录,形成中间表;然后根据SELECT的选择列选择相应的列进行返回最终结果。
    第二、两表连接查询:对两表求积(笛卡尔积)并用ON条件和连接连接类型进行过滤形成中间表;然后根据WHERE条件过滤中间表的记录,并根据SELECT指定的列返回查询结果。实例如下:

    select a.StudentID, a.Sname, b.mark 
    from TStudent a left join TScore b on a.StudentID=b.StudentID 
    where a.StudentID < 10;


    第三、多表连接查询:先对第一个和第二个表按照两表连接做查询,然后用查询结果和第三个表做连接查询,以此类推,直到所有的表都连接上为止,最终形成一个中间的结果表,然后根据WHERE条件过滤中间表的记录,并根据SELECT指定的列返回查询结果。

    过滤条件

    ON条件:过滤两个连接表笛卡尔积形成中间表的约束条件。
    WHERE条件:在有ON条件的SELECT语句中是过滤中间表的约束条件。在没有ON的单表查询中,是限制物理表或者中间查询结果返回记录的约束。在两表或多表连接中是限制连接形成最终中间表的返回结果的约束。
    将WHERE条件移入ON后面是不恰当的。推荐的做法是ON只进行连接操作,WHERE只过滤中间表的记录。

    连接查询的适用场景

    连接查询是SQL查询的核心,连接查询的连接类型选择依据实际需求。如果选择不当,非但不能提高查询效率,反而会带来一些逻辑错误或者性能低下。两表连接查询选择方式的依据:
    A、查两表关联列相等的数据用内连接。
    B、Col_L是Col_R的子集时用右连接。
    C、Col_R是Col_L的子集时用左连接。
    E、 Col_R和Col_L彼此有交集但彼此互不为子集时候用全连接。
    F、求差操作的时候用联合查询。

    ?

    其他SQL语言要素:

    常量:

    A、字符常量
    字符串常量使用单引号或双引号,数值常量不用加引号。
    \n 换行
    \’ 一个单引号
    \” 一个双引号
    \ 一个\ 如果没有转义字符 就认为\是一个转义字符
    \% 一个% 如果没有转义字符就认为这是一个通配符
    _ 一个
    ?如果没有转移字符 就认为是一个通配符如果字符串常量中需要换行、有单引号、双引号 %?\前面需要加转义字符 \

    B、数值常量
    数值常量不用添加引号,
    select 100+100+200

    C、布尔常量
    布尔型常量取值 true 和 false
    在SQL中使用1和0表示
    select true,false

    在表达式中
    select 100>200
    select 100<200

    变量:

    A、用户自定义变量使用@开始,使用set给变量赋值。
    set @name='孙悟空';
    select @name;

    B、系统变量分为全局系统变量和会话系统变量。
    全局系统变量:针对所有默认设置
    会话系统变量:针对当前用户生效,用户登录MySQL会使用全局系统变量,如果会话中更改了变量值,使用更改后的值,不过只针对当前用户生效。
    show variables 显示会话系统变量
    show global variables 显示全局系统变量
    show session variables 显示会话系统变量
    show global variables like 'sql_select_limit';使用通配符显示匹配的变量设置
    show session variables like 'sql_select_limit';系统变量使用@@标识
    select @@global.sql_select_limit 查看某个全局系统变量设置
    select @@session.sql_select_limit 查看某个会话系统变量设置
    set @@session.sql_select_limit=2 设置会话系统变量
    全局系统变量需要在/etc/my.cnf配置文件中修改。

    MySQL支持数据类型

    1、数值类型
    MySQL的数值数据类型只要分为整数和浮点数。


    MySQL支持的5个主要整型是TINYINT,SMALLINT,MEDIUMINT,INT和 BIGINT。
    MySQL 以一个可选的显示宽度指示器的形式对 SQL 标准进行扩展,这样当从数据库检索一个值时,可以把这个值加长到指定的长度。例如,指定一个字段的类型为 INT(6),就可以保证所包含数字少于 6个的值从数据库中检索出来时能够自动地用空格填充。需要注意的是,使用一个宽度指示器不会影响字段的大小和它可以存储的值的范围。
    如果对一个字段存储了一个超出许可范围的数字,MySQL会根据允许范围最接近的一端截短后再进行存储。MySQL会在不合规定的值插入表前自动修改为0。
    UNSIGNED 修饰符规定字段只保存正值。因为不需要保存数字的正、负符号,可以在储时节约一个“位”的空间。从而增大字段可以存储的值的范围。
    ZEROFILL修饰符规定0可以用来真补输出的值,可以阻止MySQL数据库存储负值。
    应用实例:
    create table tint
    (
    tid tinyint,
    tid2 tinyint unsigned,
    tid3 int(5)
    )
    alter table tint modify column tid3 int(5) zerofill
    insert into tint values (21,23,4)
    insert into tint values (11,21,233322)
    如果存储的数据溢出显示警告
    insert into tint values (221,-23,4)
    show warnings
    查看当前操作的警告信息
    FLOAT、DOUBLE和DECIMAL类型
    MySQL支持的三个浮点类型是FLOAT、DOUBLE和DECIMAL类型。FLOAT数值类型用于表示单精度浮点数值,而DOUBLE数值类型用于表示双精度浮点数值,
    附加参数是一个显示宽度指示器和一个小数点指示器。比如语句FLOAT(7,3)规定显示的值不会超过7位数字,小数点后面带有3位数字。
    对于小数点后面的位数超过允许范围的值,MySQ 会自动将它四舍五入为最接近它的值,再插入它。
    DECIMAL数据类型用于精度要求非常高的计算中,允许指定数值的精度和计数方法作为选择参数。精度在这里指为这个值保存的有效数字的总个数,而计数方法表示小数点后数字的位数。比如语句DECIMAL(7,3)规定了存储的值不会超过 7位数字,并且小数点后不超过3位。
    忽略DECIMAL数据类型的精度和计数方法修饰符将会使MySQL数据库把所有标识为这个数据类型的字段精度设置为 10,计算方法设置为 0。
    UNSIGNED和ZEROFILL修饰符也可以被FLOAT、DOUBLE和DECIMAL数据类型使用。

    2、字符串类型

    MySQL提供了8个基本的字符串类型,可以存储的范围从简单的一个字符到巨大的文本块或二进制字符串数据。


    CHAR类型用于定长字符串,并且必须在圆括号内用一个大小修饰符来定义。大小修饰符的范围从0-255。比指定长度大的值将被截短,而比指定长度小的值将会用空格作填补。
    CHAR类型可以使用BINARY修饰符。当用于比较运算时,BINARY修饰符使CHAR以二进制方式参于运算,而不是以传统的区分大小写的方式。
    CHAR类型的一个变体是VARCHAR类型,是一种可变长度的字符串类型,并且也必须带有一个范围在0-255之间的指示器。CHAR和VARCHGAR不同之处在于MySQL数据库处理范围指示器的方式:CHAR把范围大小视为值的大小,在长度不足的情况下就用空格补足;而VARCHAR类型把范围指示器视为最大值并且只使用存储字符串实际需要的长度(增加一个额外字节来存储字符串本身的长度)来存储值。短于指示器长度的VARCHAR类型不会被空格填补,但长于指示器的值仍然会被截短。
    因为VARCHAR类型可以根据实际内容动态改变存储值的长度,所以在不能确定字段需要多少字符时使用VARCHAR类型可以大大地节约磁盘空间、提高存储效率。
    VARCHAR类型在使用BINARY修饰符时与CHAR类型完全相同。
    对于字段长度要求超过255个的情况下,MySQL提供了TEXT和BLOB两种类型。根据存储数据的大小,都有不同的子类型。大型的数据用于存储文本块或图像、声音文件等二进制数据类型。
    TEXT和BLOB类型在分类和比较上存在区别。BLOB类型区分大小写,而TEXT 不区分大小写。大小修饰符不用于各种BLOB和TEXT子类型。比指定类型支持的最大范围大的值将被自动截短。

    3、日期和时间类型

    在处理日期和时间类型的值时,MySQL带有5个不同的数据类型可供选择。分为简单日期、时间类型,混合日期、时间类型。根据要求的精度,子类型在每个分类型中都可以使用,并且MySQL带有内置功能可以把多样化的输入格式变为一个标准格式。


    MySQL用DATE和YEAR类型存储简单的日期值,使用TIME类型存储时间值。日期、时间类型可以描述为字符串或不带分隔符的整数序列。如果描述为字符串,DATE类型的值应该使用连字号作为分隔符分开,而TIME类型的值使用冒号作为分隔符分开。没有冒号分隔符的TIME类型值,将会被MySQL理解为持续的时间,而不是时间戳。
    MySQL还对日期的年份中的两个数字的值,或是SQL语句中为YEAR类型输入的两个数字进行最大限度的通译。因为所有YEAR类型的值必须用4个数字存储。MySQL试图将2个数字的年份转换为4个数字的值。把在00-69范围内的值转换到2000-2069范围内。把70-99范围内的值转换到1970-1979之内。如果 MySQL自动转换后的值并不符合需要,请输入4个数字表示的年份。
    除了日期和时间数据类型,MySQL还支持DATETIME和TIMESTAMP混合类型,可以把日期和时间作为单个的值进行存储。通常用于自动存储包含当前日期和时间的时间戳,并可在需要执行大量数据库事务和需要建立一个调试和审查用途的审计跟踪的应用程序中发挥良好作用。
    如果对TIMESTAMP类型的字段没有明确赋值,或是被赋与了null值。MySQL 会自动使用系统当前的日期和时间来填充它。?
    create table dd
    (
    d DATE,
    t TIME,
    y YEAR,
    dt DATETIME,
    ts timestamp
    )
    insert into dd values ('2015-11-05','15:48:34','2015',
    '2015-11-05 15:48:34','2015-11-05 15:48:34')
    不满足时间格式的,插入后变成
    insert into dd values ('201511-05','15:78:34','15',
    '2015-11-05 154834','2015-11-05 15:48:34')

    4、复合类型

    MySQL支持两种复合数据类型ENUM和SET,属于扩展SQL规范。一个ENUM 类型只允许从一个集合中取得一个值;而SET类型允许从一个集合中取得任意多个值。?
    ENUM类型
    ENUM类型只允许在集合中取得一个值。ENUM类型字段可以从集合中取得一个值或使用null值,如果输入不在集合中的值将会使MySQL插入一个空字符串。另外如果插入值的大小写与集合中值的大小写不匹配,MySQL会自动使用插入值的大小写转换成与集合中大小写一致的值。
    ENUM类型在系统内部可以存储为数字,并且从1开始用数字做索引。一个 ENUM类型最多可以包含65536个元素,其中一个元素被MySQL保留,用来存储错误信息,错误值用索引0或者一个空字符串表示。
    MySQL认为ENUM类型集合中出现的值是合法输入,除此之外其它任何输入都将失败。通过搜索包含空字符串或对应数字索引为0的行就可以很容易地找到错误记录的位置。
    SET类型
    SET类型可以从预定义的集合中取得任意数量的值,任何试图在SET类型字段中插入非预定义的值都会使MySQL插入一个空字符串。如果插入一个即有合法的元素又有非法的元素的记录,MySQL将会保留合法的元素,除去非法的元素。
    一个SET类型最多可以包含64项元素。在SET元素中值被存储为一个分离的“位”序列,SET类型中不可能包含两个相同的元素。
    从SET类型字段中找出非法的记录只需查找包含空字符串或二进制值为0的行。
    create table dd
    (
    sname char(10),
    sex enum('男','女'),
    hobby set('游泳','旅游','打球')
    );
    insert into dd values ('韩立刚','男','游泳,打球');
    insert into dd values ('张京','难','看电影,打球');
    插入一条有错误的记录,sex列没有插入成功,hobby列只能插入set中列出的值

    ?

    运算符表达式:

    1、算术运算符

    算术运算符包括:加(+)、减(-)、乘()、除(/)、取模(%)。
    select 4+3,5-3,5
    8,20/4;
    select 17%5;
    select sid,sname,age+2 from s;

    2、比较运算符

    比较运算符包括等于(=)、大于(>)、小于(<)、大于等于(>=)、小于等于(<=)、不等于(!=或<>)
    select 10=10,10<10,10<>10;
    select binary 'a'='A','a'<'b';比较字符的二级制
    select?from s where sid<=2;
    select?
    from s where sname='孙悟空';

    3、逻辑运算符

    逻辑运算符包括与(and或&&)、或(or或||)、非(not或!)。
    逻辑运算符的应用举例
    select?from s where sname like '杨%' and age>40;
    select?
    from s where sname like '孙%' && age>30;
    select?from s where sname like '孙%' or sid<2;
    select?
    from s where sname like '孙%' || sid<2;
    select?from s where not sname like '孙%';
    select?
    from s where !(sname like '孙%');

    4、运算符优先级

    算术运算符优先级:先乘除,后加减,括号优先
    逻辑运算符优先级:先与操作,再或操作,括号优先
    sname like '韩%' and age>40 or sid<3;
    sname like '韩%' and (age>40 or sid<3);

    5、表达式

    表达式是常量、变量、运算符、函数等的组合。
    1+2;
    ‘a’<’A’;
    select * from s where age+4>40;

    6、系统内置函数

    函数大致可以分为以下几种。

    • 算术函数(用来进行数值计算的函数)
    • 字符串函数(用来进行字符串操作的函数)
    • 日期函数(用来进行日期操作的函数)
    • 转换函数(用来转换数据类型和值的函数)
    • 聚合函数(用来进行数据聚合的函数)

    ?

    • 算数函数

    ABS (数值) —— 绝对值

    MOD (被除数, 除数) —— 求余

    ROUND (对象数值, 保留小数的位数) —— 四舍五入

    ?

    • 字符串函数

    CONCAT (字符串1, 字符串2, 字符串3) —— 拼接

    LENGTH (字符串) —— 字符串长度

    LOWER (字符串) —— 小写

    UPPER (字符串) —— 大写

    REPLACE (对象字符串,替换前的字符串,替换后的字符串) —— 替换

    SUBSTRING(对象字符串 FROM 截取的起始位置 FOR 截取的字符数)—— 截取

    ?

    • 日期函数

    CURRENT_DATE —— 当前日期

    CURRENT_TIME —— 当前时间

    CURRENT_TIMESTAMP —— 当前的日期和时间

    EXTRACT (日期元素 FROM 日期)

    ?

    • 转换函数

    CAST(转换前的值 AS 想要转换的数据类型)—— 类型转换

    COALESCE (数据1,数据2,数据3……) —— 将NULL转换为其他值

    A、数学函数

    ABS(x)
    返回x的绝对值
    select * from student where abs(age-45)<=2
    查找和45岁相差不超过两岁用户

    CEIL(x),CEILING(x)
    返回大于或等于x的最小整数(向上取整)
    FLOOR(x)
    返回小于或等于x的最大整数(向下取整)
    select ceil(5.4),floor(5.6);
    select sid,sname,floor(age/10)*10 from s;

    RAND()
    返回0~1的随机数
    select floor(RAND()1000);
    产生一个0-1000的随机整数
    select?
    ,RAND() random from s order by random;
    使用随机函数随机排序查询结果
    RAND(x)
    返回0~1的随机数,种子x值相同时返回的随机数相同。

    SIGN(x)
    返回x的符号,x是负数、0、正数分别返回-1、0、1
    PI()
    返回圆周率
    TRUNCATE(x,y)
    返回数值x保留到小数点后y位的值
    select sign(-4),sign(434);
    select PI();
    select truncate(4.5454,2);
    select truncate(AVG(age),2) from s;

    ROUND(x)
    返回离x最近的整数(四舍五入)
    ROUND(x,y)
    保留x小数点后y位的值,但截断时要四舍五入
    POW(x,y),POWER(x,y)
    返回x的y次方
    SQRT(x)
    返回x的平方根
    EXP(x)
    返回自然常数e的x次方。

    B、字符串函数

    CHAR_LENGTH(s)
    返回字符串s的字符数
    LENGTH(s)
    返回字符串s的占用的空间的大小。
    select * from student where length(sname)/char_length(sname)!=3
    找到姓名中有英文字符的学生

    CONCAT(s1,s2,.....)
    将字符串s1,s2等多个字符串合并为一个字符串
    CONCAT_WS(x,s1,s2,....)
    同COUCAT(s1,s2,.....),但是每个字符串之间要加上x
    select concat('韩立刚','河北师大','网络工程师')
    select CONCAT('学号',sid,'姓名',sname,'年龄',age) from s
    select CONCAT_ws(' ','学号',sid,'姓名',sname,'年龄',age) from s

    INSERT(s1,x,len,s2)
    使用字符串s2替换s1的x位置开始长度为len的字符串
    select insert('hanligang',4,2,'zhi')
    select insert(sname,2,0,' ') from s

    UPPER(s),UCASE(s)
    将字符串s的所有字符都变成大写字母
    LOWER(s),LCASE(s)
    将字符串s的所有字符都变成小写字母
    select upper('HanLigang')
    select lower('HanLigang')
    select Upper(sname) from s

    LEFT(s,n)
    返回字符串s的前n个字符
    RIGHT(s,n)
    返回字符串s的后n个字符
    select left('孙悟空',1)
    select right('孙悟空',2)
    LPAD(s1,len,s2)
    字符串s2来填充s1的开始处,使字符串长度达到len
    RPAD(s1,len,s2)
    字符串s2来填充s1的结尾处,使字符串长度达到len
    select lpad('1',4,'0')
    select lpad(sid,4,0) from s
    select RPAD('HAN',10,'B')

    LTRIM(s)
    去掉字符串s开始处的空格
    RTRIM(s)
    去掉字符串s结尾处的空格
    TRIM(s)
    去掉字符串s开始处和结尾处的空格
    TRIM(s1 FROM s)
    去掉字符串s中开始处和结尾处的字符串s1
    用法示例:
    select char_length(LTRIM(' han '))
    select RTRIM(' han ')
    select char_length(RTRIM(' han '))
    select char_length(TRIM(' han '))
    insert into s values(10,' 张志敏',32)
    select * from s
    update s set sname=LTRIM(sname)
    select TRIM('h' from 'hanliganghhhh')

    REPEAT(s,n)
    将字符串s重复n次
    SPACE(n)
    返回n个空格
    REPLACE(s,s1,s2)
    用字符串s2代替字符串s中的字符串s1
    用法示例:
    select repeat('han',4)
    select sid,concat(left(sname,1),SPACE(sid),right(sname,2)) from s
    select replace('han li gang',' ','_')
    select replace('han li gang',' ','')

    STRCMP(s1,s2)
    如果s1小于s2,strcmp函数返回一个小于零的值。如果s1大于s2,函数返回一个大于零的值。如果两个字符串相等,函数就返回零。
    SUBSTRING(s,n,len)
    获取从字符串s中的第n个位置开始长度为len的字符串
    POSITION (s1 IN s)
    从字符串s中获取s1的开始位置
    INSTR(s,s1)
    从字符串s中获取s1的开始位置
    应用实例:
    select strcmp('han','wang')
    select strcmp('hlg','han')
    select strcmp('han','an')
    select SUBSTRING('hanligang@hotmail.com',11,7)
    select sid,SUBSTRING(sname,2,1) from s
    select SUBSTRING('hanligang@homtail.com',POSITION('@' IN 'hanligang@homtail.com')+1,11)
    select RIGHT('hanligang@homtail.com',char_length('hanligang@homtail.com')-POSITION('@' IN 'hanligang@homtail.com'))

    alter table s add email CHAR(40)
    select * from s
    update s set email='hanlihui@hotmail.com' where sid=1
    update s set email='wang@163.com' where sid=2
    update s set email='zcf@inhe.net' where sid=3;获取email字段中@后面的字符串,先截取邮箱字段的长度,在截取邮箱的@字符的位置,计算出邮箱@后面有多少字符,
    SELECT RIGHT(email,CHAR_LENGTH(email)-POSITION('@' in email)) from s
    SELECT RIGHT(email,CHAR_LENGTH(email)-INSTR(email,'@')) from s

    C、日期和时间函数

    Linux命令行查看:
    clock
    显示硬件时间
    date
    显示系统时间
    date -s 11/03/15
    更改系统日期
    date -s 9:21:4
    更改系统时间
    hwclock --systohc
    使用系统时间覆盖硬件时间
    hwclock --hctosys
    使用硬件时间覆盖系统时间
    MySQL命令行查看:
    curdate()
    CURRENT_DATE()
    获取系统当前日期
    curtime()
    CURRENT_TIME()
    获取系统当前时间
    CURRENT_TIMESTAMP()
    LOCALTIME()
    NOW()
    获取系统当前日期和时间

    应用实例:
    给表s增加一列,数据类型timestamp 默认值是当前时间。
    alter table s add stime TIMESTAMP default now();
    select * from s
    insert into s (sid,sname,age,email) values (11,'张东',34,'zhangd@sohu.com')
    将以前用户的stime列更改为当前时间
    update s set stime=now() where sid<11
    返回日期d中的月份值,范围是1~12
    MONTH(d)
    返回日期d中的月份名称,如january
    MONTHNAME(d)
    返回日期d是星期几,如Monday
    DAYNAME(d)
    返回日期d是星期几,1表示星期日,2表示星期1
    DAYOFWEEK(d)
    返回日期d是星期几,0表示星期一,1表示星期2
    WEEKDAY(d)
    计算日期d是本年的第几个星期,范围是0-53
    WEEK(d)

    计算日期d是本年的第几个星期,范围是1-53
    WEEKOFYEAR(d)
    计算日期d是本年的第几天
    DAYOFYEAR(d)
    计算日期d是本月的第几天
    DAYOFMONTH(d)
    返回日期d中的年份值
    YEAR(d)
    返回日期d是第几季度,范围1-4
    QUARTER(d)
    返回时间t中的小时值
    HOUR(t)
    返回时间t中的分钟值
    MINUTE(t)
    返回时间t中的秒钟值
    SECOND(t)

    应用实例:
    select concat(year(now()),'年',month(now()),'月',DAY(now()),'日')
    select CONCAT(year(stime),'年',month(stime),'月',DAY(stime),'日') from s

    计算日期d1到d2之间相隔的天数
    DATEDIFF(d1,d2)

    计算开始日期d加上n天的日期
    ADDDATE(d,n)

    计算起始日期d加上一个时间段后的日期
    ADDDATE(d, INTERVAL expr type)

    计算起始时间t加上n秒的时间
    ADDTIME(t,n)

    应用实例:
    select datediff(now(),'2015-2-3')
    select ADDDATE(now(),-1050)
    select ADDDATE(now(),1050)

    select ADDDATE(now(), INTERVAL 1000000 SECOND)
    select ADDDATE(now(), INTERVAL 1000000 hour)
    select ADDDATE(now(), INTERVAL -10000 day)
    select ADDDATE(now(), INTERVAL '10 3' DAY_HOUR)
    select ADDDATE(now(), INTERVAL 3 year)

    D、系统信息函数

    系统信息函数用来查询MySQL数据库的系统信息。例如查询数据库的版本,查询数据的当前用户等。
    VERSION()
    返回数据库的版本号
    CONNECTION_ID()
    返回服务器的连接数,也就是到现在为止mysql服务的连接次数
    DATABASE(),SCHEMA()
    返回当前数据库名
    USER()
    返回当前用户的名称
    CHARSET(str)
    返回字符串str的字符集
    COLLATION(str)
    返回字符串str的字符排列方式
    LAST_INSERT_ID()
    返回最后生成的auto_increment值

    E、加密解密函数

    加密函数是MySQL中用来对数据进行加密的函数。
    PASSWORD(str)
    对字符串str进行加密
    MD5(str)
    对字符串str进行MD5加密
    ENCODE(str,pswd_str)
    使用字符串pswd_str来加密字符串str,加密结果是一个二进制数,必须使用BLOB类型来保存
    DECODE(crypt_str,pswd_str)
    解密函数,使用字符串pswd_str来为crypt_str解密

    应用实例:
    create table webuser
    (
    logon varchar(20),
    pw VARCHAR(100)
    );
    insert into webuser values ('hanligang',md5('abc'));
    insert into webuser values ('zhangql',md5('123'));
    select?from webuser where logon='hanligang' and pw=MD5('abc');
    ALTER TABLE?webuser?MODIFY COLUMN?pw?BLOB(1);
    insert into webuser values ('zhangjing',encode('abcd','91xueit'));
    select logon,decode(pw,'91xueit') from webuser;
    select?
    from webuser where logon='zhangjing' and decode(pw,'91xueit')='abcd';

    F、聚合函数

    Count()
    统计满足条件的记录数量
    select count(*) from s
    统计表中有多少条记录
    select COUNT(email) from s
    select COUNT(all email) from s
    统计表中email列有多少条有值的记录,包括重复值
    select COUNT(distinct email) from s
    统计表中email列有多少条有值的记录 消除重复值

    Sum() 统计总数
    select SUM(age) from s where email is not null

    Avg() 求平均值
    select avg(age) from s where email is not null
    Max() 求最大值
    Min() 求最小值
    select avg(age),MAX(age),MIN(age) from s

    group_concat() 将满足条件的记录,显示成一行,使用逗号分开
    select group_concat(sname) from s where sid<5

    G、条件判断函数

    IF(value,t,f) 如果value是true t 如果是false 返回值f
    select sname,IF(age>40,'中年','青年') as age from s

    ifnull(value1,value2) 如果value1不为空,返回value1,如果value1为空,返回value2
    select sname,IFNULL(email,'没有邮箱') as 邮箱 from s

    Case when value1 then result1 else default end
    当value1值是true 返回result1,否则返回default值
    select sname,case when age>40 then '中年' else '青年' end from s

    Case expr when value1 then ‘result1’ when value2 then ‘result2’ when value3 then ‘result3’ else ‘result4’ end
    根据expr表达式的值,返回不同的值
    select sname, case floor(age/10) when 2 then '壮年' when 3 then '青年' else '中年' end from s

    H:数据类型转换函数

    类型转换函数主要是CAST(xxx AS 类型), CONVERT(xxx,类型)。可以转换的类型是有限制的,包括二进制、字符型、日期、时间、日期时间型、浮点数、整数、无符号整数。
    select CAST('00033ad' as signed)
    select CONVERT(44.334,signed)
    select concat(CONVERT(44.334,char(10)),'3000')
    类型自动推导转换
    select '0033aa'+23
    select CONCAT(123,'abc',123)

    I:格式化函数:FORMAT();

    本文地址:https://blog.csdn.net/guangod/article/details/108941248