《mysql必知必会》读书笔记(中)

本文详细介绍了MySQL中的数据处理函数,如文本转换、SOUNDEX算法,日期和时间格式,数值处理,聚集函数如AVG、COUNT和MAX,分组数据,子查询的使用,全文本搜索,以及数据的插入方法。
摘要由CSDN通过智能技术生成

第十一章 使用数据处理函数

文本处理函数
# Upper()将文本转换为大写
select name,Upper(name) AS name_upcase from product;
# 。SOUNDEX()是一个将任何文本串转换为描述其语音表示的字母数字模式的算法。SOUNDEX考虑了类似的发音字符和音节,使得能对串进行发音比较而不是字母比较
select name from product where Soundex(name) = Soundex('Y Lie');
日期和时间处理函数
  • 是MySQL使用的日期格式。无论你什么时候指定一个日期,不管是插入或更新表值还是用WHERE子句进行过滤,日期必须为格式yyyy-mm-dd。虽然其他的
    日期格式可能也行,但这是首选的日期格式,因为它排除了多义性。
  • 如果你想要的仅是日期,则使用Date()是一个良好的习惯。
select order_id,order_price from order WHERE order_date = '2005-09-01';
# 如果数据库中存储的类型为datetime。这种类型存储日期及时间值。样例表中的值全都具有时间值00:00:00。
# 解决办法是指示MySQL仅将给出的日期与列中的日期部分进行比较,而不是将给出的日期与整个列值进行比较。为此,必须使用Date()函数。Date(order_date)指示MySQL仅提取列的日期部分,更可靠的SELECT语句为:
select order_id,order_price from order WHERE Date(order_date) = '2005-09-01';

# 检索2005年九月所有的订单
select * from order WHERE Year(order_date)= 2005 AND Month(order_date) = 9;

数值处理函数
  • 数值处理函数仅处理数值数据。这些函数一般主要用于代数、三角或几何运算,因此没有串或日期—时间处理函数的使用那么频繁。
  • 有正弦,余弦,绝对值等。

第十二章 汇总数据

聚集函数
  • 聚集函数(aggregate function) 运行在行组上,计算和返回单个值的函数。
  • 如:AVG()通过对表中行数计数并计算特定列值之和,求得该列的平均值。AVG()可用来返回所有列的平均值,也可以用来返回特定列或行的平
    均值。
# 使用AVG()返回product表中所有产品的平均价格。
select AVG(price) AS avg_price from product;
# AVG()也可以用来确定特定列或行的平均值。AVG()函数忽略列值为NULL的行。

# COUNT()函数有两种使用方式。
# 1. 使用COUNT(*)对表中行的数目进行计数,不管表列中包含的是空值(NULL)还是非空值。
# 2. 使用COUNT(column)对特定列中具有值的行进行计数,忽略NULL值。
select COUNT(price) from product;

# MAX()一般用来找出最大的数值或日期值,但MySQL允许将它用来返回任意列中的最大值,包括返回文本列中的最大值。在用于文本数据时,如果数据按相应的列排序,则MAX()返回最后一行。MAX()函数忽略列值为NULL的行。

聚集不同值
# 只包含不同的值,指定DISTINCT参数,只计算不同价格的平均值。
# DISTINCT必须使用列名。
select AVG(DISTINCT price) AS avg_price from product;

组合聚集函数
  • 目前为止的所有聚集函数例子都只涉及单个函数。但实际上SELECT语句可根据需要包含多个聚集函数。
select AVG(price) AS avg_price,count(*) AS items_num from product;

第十三章 分组数据

创建分组
  • 分组是在SELECT语句的GROUP BY子句中建立的。
  • 如果分组列中具有NULL值,则NULL将作为一个分组返回。如果列中有多行NULL值,它们将分为一组。
  • GROUP BY子句必须出现在WHERE子句之后,ORDER BY子句之前。
过滤分组
  • WHERE过滤指定的是行而不是分组。
  • MySQL为此目的提供了另外的子句,那就是HAVING子句。HAVING非常类似于WHERE。唯一的差别是WHERE过滤行,而HAVING过滤分组。
  • HAVING支持所有WHERE操作符。
  • 这里有另一种理解方法,WHERE在数据分组前进行过滤,HAVING在数据分组后进行过滤。这是一个重要的区别,WHERE排除的行不包括在分组中。这可能会改变计算值,从而影响HAVING子句中基于这些值过滤掉的分组。
# 加了HAVING子句,它过滤COUNT(*) >=2(两个以上的订单)的那些分组。
# 正如所见,这里WHERE子句不起作用,因为过滤是基于分组聚集值而不是特定行值的。
select order_id,count(*) AS items_num from order GROUP BY order_id HAVING COUNT(*) >=2;

分组和排序
  • order by :排序产生的输出,任意列都可以使用。
select AVG(price) AS avg_price,count(*) AS items_num from product order by price;

select子句顺序
  • select > from > where > group by > having > order by > limit

第十四章 使用子查询

利用子查询进行过滤
  • 在SELECT语句中,子查询总是从内向外处理。
  • 包含子查询的SELECT语句难以阅读和调试,特别是它们较为复杂时更是如此。如上所示把子查询分解为多行并且适当地进行缩进,能极大地简化子查询的使用。
  • 列必须匹配 在WHERE子句中使用子查询(如这里所示),应该保证SELECT语句具有与WHERE子句中相同数目的列。通常,子查询将返回单个列并且与单个列匹配,但如果需要也可以使用多个列。
  • 实际使用时由于性能的限制,不能嵌套太多的子查询。
select cust_name,cust_contact from customers
where cust_id IN (select cust_id
                  from orders
                  where order_num IN (select order_num
                                      from orderitems
                                      where prod_id = '1002'));

作为计算字段使用子查询
  • 将子查询的结果作为一个字段使用。
select cust_name,cust_contact,(select count(*)
                  from orders
                  where order_num IN ('1002','1003')) AS orders
                  from customers;

相关子查询
  • 涉及外部查询的子查询。任何时候只要列名可能有多义性(即两个表的有相同的字段属性),就必须使用这种语法(表名和列名由一个句点分隔)。
构造子查询技巧
  • 用子查询建立(和测试)查询的最可靠的方法是逐渐进行,
  • 这与MySQL处理它们的方法非常相同。首先,建立和测试最内层的查询。然后,用硬编码数据建立和测试外层查询,并且输入,输出,分析,仅在确认它正常后才嵌入子查询。这时,再次测试它。对于要增加的每个查询,重复这些步骤。
  • 这样做仅给构造查询增加了一点点时间,但节省了以后(找出查询为什么不正常)的大量时间,并且极大地提高了查询一开始就正常工作的可能性。

联结表

关系表
  • 关系表的设计就是要保证把信息分解成多个表,一类数据一个表。各表通过某些常用的值(即关系设计中的关系(relational))互相关联。
  • 外键(foreign key) 外键为某个表中的一列,它包含另一个表的主键值,定义了两个表之间的关系。
  • 用来在一条SELECT语句中关联表,因此称之为联结。
  • 在引用的列可能出现二义性时,必须使用完全限定列名(用一个点分隔的表名和列名)。如果引用一个没有用表名限制的具有二义性的列名,MySQL将返回错误。
内部联结
# 目前为止所用的联结称为等值联结(equijoin),它基于两个表之间的相等测试。这种联结也称为内部联结.
select name,price from vendor 
    inner join products 
    on vendors.vend_id = products.vendors.vend_id;
联结多个表
  1. SQL对一条SELECT语句中可以联结的表的数目没有限制。创建联结的基本规则也相同。

第十六章 创建高级联结

自联结
# 此查询中需要的两个表实际上是相同的表,因此products表在FROM子句中出现了两次。
# 虽然这是完全合法的,但对products的引用具有二义性,因为MySQL不知道你引用的是products表中的哪个实例。为解决此问题,使用了表别名。
select p1.prod_id,p1.prod_name from products AS p1, products AS p2
    where p1.vend_id = p2.vend_id
    AND p2.prod_id = 'DTNTO';
外部联结
  • 联结包含了那些在相关表中没有关联行的行。这种类型的联结称为外部联结。
  • 存在两种基本的外部联结形式:左外部联结和右外部联结。它们之间的唯一差别是所关联的表的顺序不同。换句话说,左外部联结可通过颠倒FROM或WHERE子句中表的顺序转换为右外部联结。因此,两种类型的外部联结可互换使用,而究竟使用哪一种纯粹是根据方便而定。
# 检索每一个客户的订单数量。为了检索所有客户,包括那些没有订单的客户,使用外部联结,可如下进行:
# 使用LEFT OUTER JOIN从FROM子句的左边表(customers表)中选择所有行
select customers.cust_id,orders.order_num 
    from customers LEFT OUTER JOIN orders
    ON customers.cust_id = orders.cust_id;
  • 10002用户在order表内没有任何数据,但是使用外部联结依旧检索出来记录。记录显示为null 。

在这里插入图片描述

第十七章 组合查询

组合查询
  • 有两种基本情况,其中需要使用组合查询:① 在单个查询中从不同的表返回类似结构的数据;② 对单个表执行多个查询,按单个查询返回数据。
  • UNION的使用很简单。所需做的只是给出每条SELECT语句,在各条语句之间放上关键字UNION。
  • 案例
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
UNION规则
  1. 在进行并时有几条规则需要注意。
    • UNION必须由两条或两条以上的SELECT语句组成,语句之间用关键字UNION分隔(因此,如果组合4条SELECT语句,将要使用3个UNION关键字)。
    • UNION中的每个查询必须包含相同的列、表达式或聚集函数(不过各个列不需要以相同的次序列出)。
    • 列数据类型必须兼容:类型不必完全相同,但必须是DBMS可以隐含地转换的类型(例如,不同的数值类型或不同的日期类型)。
  2. UNION从查询结果集中自动去除了重复的行。如果想返回所有匹配行,可使用UNION ALL而不是UNION。
对组合查询结果进行排序
  1. SELECT语句的输出用ORDER BY子句排序。在用UNION组合查询时,只能使用一条ORDER BY子句,它必须出现在最后一条SELECT语句之后。
  2. 对于结果集,不存在用一种方式排序一部分,而又用另一种方式排序另一部分的情况,因此不允许使用多条ORDER BY子句。

第十八章 全文本搜索

理解全文本搜索
  1. 并非所有引擎都支持全文本搜索,两个最常使用的引擎为MyISAM和InnoDB,前者支持全文本搜索,而后者不支持。
启用全文本搜索支持
  1. 一般在创建表时启用全文本搜索。CREATE TABLE语句中接受FULLTEXT子句,它给出被索引列的一个逗号分隔的列表。
# 列中有一个名为note_text的列,为了进行全文本搜索,MySQL根据子句FULLTEXT(note_text)的指示对它进行索引。这里的FULLTEXT索引单个列,如果需要也可以指定多个列。在定义之后,MySQL自动维护该索引。在增加、更新或删除行时,索引随之自动更新。
    create table productnotes{
        note_id int not null,
        prod_id char(10) not null,
        note_text text null,
        FULLTEXT(note_text)
    }ENGINE=MyISAM;
# 可以在创建表时指定FULLTEXT,或者在稍后指定(在这种情况下所有已有数据必须立即索引)。
进行全文本搜索
  • 在索引之后,使用两个函数Match()和Against()执行全文本搜索,其中Match()指定被搜索的列,Against()指定要使用的搜索表达式。
  • 传递给 Match() 的值必须与FULLTEXT()定义中的相同。如果指定多个列,则必须列出它们(而且次序正确)。
# Match(note_text)指示MySQL针对指定的列进行搜索,Against('rabbit')指定词rabbit作为搜索文本。
# 两个行都包含词rabbit,但包含词rabbit作为第3个词的行的等级比作为第20个词的行高。这很重要。全文本搜索的一个重要部分就是对结果排序。具有较高等级的行先返回(因为这些行很可能是你真正想要的行)。
    select note_text
    from productnotes
    where Match(note_text) Against('rabbit');
# 在SELECT而不是WHERE子句中使用Match()和Against()。这使所有行都被返回(因为没有WHERE子句)。Match()和Against()用来建立一个计算列(别名为rank),此列包含全文本搜索计算出的等级值。等级由MySQL根据行中词的数目、唯一词的数目、整个索引中词的总数以及包含该词的行的数目计算出来。正如所见,不包含词rabbit的行等级为0(因此不被前一例子中的WHERE子句选择)。确实包含词rabbit的两个行每行都有一个等级值,文本中词靠前的行的等级值比词靠后的行的等级值高
    select note_text,Match(note_text) Against('rabbit') AS rank
    from productnotes;
# 由于数据是索引的,全文本搜索还相当快
使用查询扩展
  • 查询扩展用来设法放宽所返回的全文本搜索结果的范围。
  • 你想找出所有提到anvils的注释。只有一个注释包含词anvils,但你还想找出可能与你的搜索有关的所有其他行,即使它们不包含词anvils。
# 第一行包含词anvils,因此等级最高。第二行与anvils无关,但因为它和第一行中共有一些相同的词,也会被检索出来。
    select note_text
    from productnotes
    where Match(note_text) Against('rabbit' WITH QUERY EXPANSION);
布尔文本搜索
  1. MySQL支持全文本搜索的另外一种形式,称为布尔方式(boolean mode)。即使没有FULLTEXT索引也可以使用。
    • 要匹配的词;
    • 要排斥的词(如果某行包含这个词,则不返回该行,即使它包含其他指定的词也是如此);
    • 排列提示(指定某些词比其他词更重要,更重要的词等级更高);
    • 表达式分组;
    • 另外一些内容。
# 此全文本搜索检索包含词heavy的所有行(有两行)。其中使用了关键字IN BOOLEAN MODE,但实际上没有指定布尔操作符,因此,其结果与没有指定布尔方式的结果相同。
    select note_text
    from productnotes
    where Match(note_text) Against('heavy' IN BOOLEAN MODE);
#为了匹配包含heavy但不包含任意以rope开始的词的行,可使用以下查询:
    select note_text
    from productnotes
    where Match(note_text) Against('heavy -rope*' IN BOOLEAN MODE);

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

第十九章 插入数据

插入完整的行
  • 没有输出 INSERT语句一般不会产生输出。
# 存储到每个表列中的数据在VALUES子句中给出,对每个列必须提供一个值。如果某个列没有值(如上面的cust_contact和cust_email列),应该使用NULL值(假定表允许对该列指定空值)。各个列必须以它们在表定义中出现的次序填充。第一列cust_id也为NULL。这是因为每次插入一个新行时,该列由MySQL自动增量。你不想给出一个值(这是MySQL的工作),又不能省略此列(如前所述,必须给出每个列),所以指定一个NULL值(它被MySQL忽略,MySQL在这里插入下一个可用的cust_id值)。
# 不安全
insert into customers
values (null,'aa','90');
# 指定列去插入更安全
insert into customers(cust_id,cust_name,cust_num)
values (null,'aa','90');
插入多个行
  • 可以使用多条INSERT语句,甚至一次提交它们,每条语句用一个分号结束。
  • 只要每条INSERT语句中的列名(和次序)相同,可以如下组合各语句。
# 其中单条INSERT语句有多组值,每组值用一对圆括号括起来,用逗号分隔。
# 此技术可以提高数据库处理的性能,因为MySQL用单条INSERT语句处理多个插入比使用多条INSERT语句快。
insert into customers(cust_id,cust_name,cust_num)
values (null,'aa','90'),(null,'bb','901');
插入检索出的数据
  • INSERT还存在另一种形式,可以利用它将一条SELECT语句的结果插入表中。这就是所谓的INSERT SELECT。
  • 假如你想从另一表中合并客户列表到你的customers表。不需要每次读取一行,然后再将它用INSERT插入。
# 这个例子使用INSERT SELECT从custnew中将所有数据导入customers。SELECT语句从custnew检索出要插入的值,而不是列出它们。SELECT中列出的每个列对应于customers表名后所跟的列表中的每个列。这条语句将插入多少行有赖于custnew表中有多少行。如果这个表为空,则没有行被插入(也不产生错误,因为操作仍然是合法的)。如果这个表确实含有数据,则所有数据将被插入到customers。这个例子导入了cust_id(假设你能够确保cust_id的值不重复)。你也可以简单地省略这列(从INSERT和SELECT中),这样MySQL就会生成新值(自增主键)。
insert into customers (cust_id,cust_contract)
        select cust_id,cust_contract from custnew;
# SELECT语句中使用了相同的列名。但是,不一定要求列名匹配。事实上,MySQL甚至不关心SELECT返回的列名。它使用的是列的位置。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值