学习笔记,来源:实验楼 ,连接: https://www.shiyanlou.com/courses/9mysql

1、日期计算:
一、要想肯定每一个宠物有多大,可使用函数TIMESTAMPDIFF()计算当前日期的年和出生日期之间的差也能够按照直接使用语句
(YEAR(CURDATE())-YEAR(birth))计算,其中函数
CURDATE()是计算当前的日期。若是当前日期的日历年比出生日期早,则减去一年。如下代码是查询每一个宠物的出生日期、当前日期和年龄(以年做为计算单位),其中关键字age是年龄这个计算结果的标签。
SELECT name, birth, CURDATE(),TIMESTAMPDIFF(YEAR,birth,CURDATE()) AS age FROM pet; SELECT name, birth, CURDATE(), (YEAR(CURDATE())-YEAR(birth)) - (RIGHT(CURDATE(),5)<RIGHT(birth,5)) AS age FROM pet ORDER BY name;
YEAR()提取日期的年部分,
RIGHT()提取日期最右面5个字符的MM-DD (月份和日期)部分。
二、查询来肯定已经死亡动物的死亡年龄。你经过检查death值是否为NULL来肯定是哪些动物已经死亡,而后对于那些非NULL值的动物,须要计算出death和birth值之间的差来知道他们在这个世界上所存在的时间:
SELECT name, birth, death, (YEAR(death)-YEAR(birth)) - (RIGHT(death,5)<RIGHT(birth,5)) AS age FROM pet WHERE death IS NOT NULL ORDER BY age;
查询使用
death IS NOT NULL而非death != NULL,由于NULL是特殊的值,不能使用普通比较符来比较。
三、哪一个动物下个月过生日怎么办?对于这类计算,年和天是无关的,你只须要提取birth列的月份部分。MySQL提供几个日期方面的提取函数,例如
YEAR()、MONTH()和
DAYOFMONTH()。在这里MONTH()是咱们须要的函数。为了观察它的实现原理,能够运行如下简单的查询显示birth和MONTH(birth)的值:
SELECT name, birth FROM pet WHERE MONTH(birth) = MONTH(DATE_ADD(CURDATE(),INTERVAL 1 MONTH));、
DATE_ADD()容许在一个给定的日期上加上时间间隔。若是在NOW()值上加上一个月,而后用MONTH()提取月份,产生生日所在月份
四、完成该任务的另外一个方法是加1得出当前月份的下一个月(在使用取模函数
MOD()后,若是月份当前值是12,则“返回”到值0):
SELECT name, birth FROM pet WHERE MONTH(birth) = MOD(MONTH(CURDATE()), 12) + 1;
注意,MONTH返回在1和12之间的一个数字,且MOD(something,12)返回在0和11之间的一个数字,所以必须在MOD()后加1,不然咱们将从11月(11)跳到1月(1)。
2、模式匹配:
一、MySQL提供标准的SQL模式匹配,以及一种基于类Unix里的程序如vi、grep和sed里的扩展正则表达式模式匹配的格式。 SQL模式匹配容许你使用
“_”匹配任何单个字符,而
“%”匹配任意数目字符(包括零字符)。在 MySQL中,SQL的模式默认是忽略大小写的。下面给出一些例子。注意使用SQL模式时,不能使用=或!=;而应使用LIKE或NOT LIKE比较操做符。
要想找出以“b”开头的名字的动物信息:
mysql> SELECT * FROM pet WHERE name LIKE 'b%';
要想找出以“fy”结尾的名字:
mysql> SELECT * FROM pet WHERE name LIKE '%fy';
要想找出包含“w”的名字:
mysql> SELECT * FROM pet WHERE name LIKE '%w%';
要想找出正好包含5个字符的名字,使用“_”模式字符:
mysql> SELECT * FROM pet WHERE name LIKE '_____';
二、由MySQL提供的模式匹配的其它类型是使用扩展正则表达式。当你对这类模式进行匹配测试时,使用
REGEXP和
NOT REGEXP操做符(或
RLIKE和
NOT RLIKE,它们是同义词)。
扩展正则表达式的一些字符是:
- ‘.’匹配任何单个的字符。
- 字符类“[...]”匹配在方括号内的任何字符。例如,“[abc]”匹配“a”、“b”或“c”。为了命名字符的范围,使用一个“-”。“[a-z]”匹配任何字母,而“[0-9]”匹配任何数字。
- “ ”匹配零个或多个在它前面的字符。例如,“x”匹配任何数量的“x”字符,“[0-9]”匹配任何数量的数字,而“.”匹配任何数量的任何字符。
若是
REGEXP模式与被测试值的任何地方匹配,模式就匹配(这不一样于LIKE模式匹配,只有与整个值匹配,模式才匹配)。 为了定位一个模式以便它必须匹配被测试值的开始或结尾,在模式开始处使用“^”或在模式的结尾用“$”。 为了说明扩展正则表达式如何工做,下面使用REGEXP重写上面所示的LIKE查询:
为了找出以“b”开头的名字,使用“^”匹配名字的开始:
mysql> SELECT * FROM pet WHERE name REGEXP '^b';
若是你想强制使REGEXP比较区分大小写,使用BINARY关键字使其中一个字符串变为二进制字符串。该查询只匹配名称首字母的小写‘b’。
mysql> SELECT * FROM pet WHERE name REGEXP BINARY '^b';
为了找出以“fy”结尾的名字,使用“$”匹配名字的结尾:
mysql> SELECT * FROM pet WHERE name REGEXP 'fy$';
为了找出包含一个“w”的名字,使用如下查询:
mysql> SELECT * FROM pet WHERE name REGEXP 'w';
三、既然若是一个正则表达式出如今值的任何地方,他就会被模式匹配,就没必要在先前的查询中在模式的两侧放置一个通配符以使得它匹配整个值,就像你使用了一个SQL模式那样。
为了找出包含正好5个字符的名字,使用“^”和“$”匹配名字的开始和结尾,和5个“.”实例在二者之间:
mysql> SELECT * FROM pet WHERE name REGEXP '^.....$';
你也可使用“{n}”重复n次操做符,重写前面的查询:
mysql> SELECT * FROM pet WHERE name REGEXP '^.{5}$';
3、计算行数:
计算你拥有动物的总数目与“在pet表中有多少行?”是一样的问题,由于每一个宠物都对应一条记录。COUNT(*)函数计算行数,因此计算动物数目的查询应为:
mysql> SELECT COUNT(*) FROM pet;
若是你想要知道每一个主人有多少宠物,你也可使用COUNT(*)函数:
mysql> SELECT owner, COUNT(*) FROM pet GROUP BY owner;
注意,使用GROUP BY对每一个owner的全部记录分组,没有它,你会获得错误消息:
mysql> SELECT owner, COUNT(*) FROM pet;
ERROR 1140 (42000): Mixing of GROUP columns (MIN(),MAX(),COUNT(),...)
with no GROUP columns is illegal if there is no GROUP BY clause
COUNT(*)和GROUP BY以各类形式分类你的数据。下列例子显示出以不一样方式进行动物普查操做。
查看每种动物的数量:
mysql> SELECT species, COUNT(*) FROM pet GROUP BY species;
查看每种性别的动物数量:
mysql> SELECT sex, COUNT(*) FROM pet GROUP BY sex;
按种类和性别组合分类的动物数量:
mysql> SELECT species, sex, COUNT(*) FROM pet GROUP BY species, sex;
若使用COUNT(*),你没必要检索整个表。例如, 当只对狗和猫进行查询时,应为:
mysql> SELECT species, sex, COUNT(*) FROM pet WHERE species = 'dog' OR species = 'cat' GROUP BY species, sex;
或,若是你仅须要知道已知性别的按性别分组的动物数目: 正则表达式
mysql> SELECT species, sex, COUNT(*) FROM pet WHERE sex IS NOT NULL GROUP BY species, sex;
4、使用1个以上的表
pet表追踪你拥有的宠物。若是你想要记录其它相关信息,例如在他们看兽医的状况或后代出生的状况,那么你须要另外的表。这张表应该拥有些什么呢?它须要:
须要包含宠物名字以便你知道每一个发生的事件属于哪一个动物。
须要一个日期以便你知道事件是何时发生的。
须要一个描述事件的字段。
若是你想要对事件进行分类,则须要一个事件类型字段。
综上所述,
event表的CREATE TABLE语句应为:
mysql> CREATE TABLE event (name VARCHAR(20), date DATE, type VARCHAR(15), remark VARCHAR(255));
相似于于pet表,最简单的方法是建立一个用定位符分隔的文本文件来加载载初始记录:
采用以下方式加载记录:
mysql> LOAD DATA LOCAL INFILE '/home/shiyanlou/Desktop/event.txt' INTO TABLE event;
因为你已经在
pet表上的查询中学到了必定的知识,你应该能执行对
event表中记录的检索;原理是同样的。可是有没有event表自己不能回答你可能问的问题呢?
当宠物们生了了一窝小动物时,假定你想要找出这时候每只宠物的年龄。咱们前面看到了如何经过两个日期计算年龄。event表中有母亲的生产日期,可是为了计算母亲的年龄,你须要她的出生日期,存储在pet表中。说明查询须要两个表:
mysql> SELECT pet.name,
-> (YEAR(date)-YEAR(birth)) - (RIGHT(date,5)<RIGHT(birth,5)) AS age,
-> remark
-> FROM pet, event
-> WHERE pet.name = event.name AND event.type = 'litter';
关于该查询要注意如下几件事:
FROM子句链接两个表,由于查询须要从两个表中提取信息。
当从多个表组合(联结)信息时,你须要指定其中一个表中的列明以期匹配其它表的列名。这很简单,由于它们都有一个name列,查询能够经过使用WHERE子句基于name值来匹配两个表中的记录。
由于name列都存在两个表中,所以
当引用该列时,必定要指定是哪一个表,把表名附在列名前便可以实现。 若是你想要将一个表的记录与该表的其它记录进行比较,能够将该表联结到自身。例如,为了在你的宠物之中选择繁殖中的配偶,你能够用pet表联结自身来进行相同种类的雄雌配对:
mysql> SELECT p1.name, p1.sex, p2.name, p2.sex, p1.species
-> FROM pet AS p1, pet AS p2
-> WHERE p1.species = p2.species AND p1.sex = 'f' AND p2.sex = 'm';
在这个查询中,咱们为表名指定别名p1和p2以便能引用它们的列而且使得每个列的引用更直观。
5、得到数据库和表的信息
一、若是你忘记数据库或表的名字,或给定的表的结构是什么(例如,它的列叫什么),怎么办?MySQL提供一些语句解决这个问题。 你已经知道SHOW DATABASES能够列出由服务器管理的全部数据库。为了找出当前选择了哪一个数据库,使用
DATABASE()函数:
mysql> SELECT DATABASE();
若是你还没选择任何数据库,结果是
NULL。
二、为了找出当前的数据库包含什么表(例如,当你不能肯定一个表的名字),使用这个命令:
三、若是你想要知道一个表的结构,可使用
DESCRIBE命令;它显示表中每一个列的信息:
Field显示列名字,
Type是列的数据类型,
Null表示列是否能包含NULL值,
key显示列是否被索引而
Default指定列的默认值。
若是表有索引,SHOW INDEX FROM tbl_name生成有关索引的信息。