MySQL入门教程5 —— 从数据表中检索信息

select语句用来从数据表检索信息。语句的一般格式是:

SELECT what_to_select FROM which_table WHERE conditions_to_satisfy;

what_to_select指出你想要看到的内容,可以是列的一个表,或*表示“所有的列”。which_table指出你想要从其检索数据的表。WHERE子句是可选项,如果选择该项,conditions_to_satisfy指定行必须满足的检索条件。

1. 选择所有数据

SELECT最简单的形式是从一个表中检索所有记录:

mysql> SELECT * FROM pet; +----------+--------+---------+------+------------+------------+| name     | owner  | species | sex  | birth      | death      |+----------+--------+---------+------+------------+------------+| Fluffy   | Harold | cat     | f    | 1993-02-04 | NULL       || Claws    | Gwen   | cat     | m    | 1994-03-17 | NULL       || Buffy    | Harold | dog     | f    | 1989-05-13 | NULL       || Fang     | Benny  | dog     | m    | 1990-08-27 | NULL       || Bowser   | Diane  | dog     | m    | 1979-08-31 | 1995-07-29 || Chirpy   | Gwen   | bird    | f    | 1998-09-11 | NULL       || Whistler | Gwen   | bird    | NULL | 1997-12-09 | NULL       || Slim     | Benny  | snake   | m    | 1996-04-29 | NULL       || Puffball | Diane  | hamster | f    | 1999-03-30 | NULL       |+----------+--------+---------+------+------------+------------+

如果你想要浏览整个表,可以使用这种形式的SELECT,例如,刚刚装载了初始数据集以后。也有可能你想到Bowser的生日看起来不很对。查阅你原来的家谱,你发现正确的出生年是1989,而不是1979。

至少有两种修正方法:

·编辑文件“pet.txt”改正错误,然后使用DELETE和LOAD DATA清空并重新装载表:

 mysql> DELETE FROM pet; mysql> LOAD DATA LOCAL INFILE 'pet.txt' INTO TABLE pet;

然而, 如果这样操做,必须重新输入Puffball记录。

·用一个UPDATE语句仅修正错误记录:

mysql> UPDATE pet SET birth = '1989-08-31' WHERE name = 'Bowser';

UPDATE只更改有问题的记录,不需要重新装载数据库表。

2. 选择特殊行

如上所示,检索整个表是容易的。只需要从SELECT语句中删掉WHERE子句。但是一般你不想看到整个表,特别地当表变得很大时。相反,你通常对回答一个具体的问题更感兴趣,在这种情况下在你想要的信息上进行一些限制。让我们看一些他们回答的有关你宠物的问题的选择查询。可以从表中只选择特定的行。例如,如果你想要验证你对Bowser的生日所做的更改,按下述方法选择Bowser的记录:

mysql> SELECT * FROM pet WHERE name = 'Bowser'; +--------+-------+---------+------+------------+------------+| name   | owner | species | sex  | birth      | death      |+--------+-------+---------+------+------------+------------+| Bowser | Diane | dog     | m    | 1989-08-31 | 1995-07-29 |+--------+-------+---------+------+------------+------------+

输出证实正确的年份记录为1989,而不是1979。

字符串比较时通常对大小些不敏感,因此你可以将名字指定为”bowser”、”BOWSER”等,查询结果相同。

你可以在任何列上指定条件,不只仅仅是name。例如,如果你想要知道哪个动物在1998以后出生的,测试birth列:

mysql> SELECT * FROM pet WHERE birth > '1998-1-1'; +----------+-------+---------+------+------------+-------+| name     | owner | species | sex  | birth      | death |+----------+-------+---------+------+------------+-------+| Chirpy   | Gwen  | bird    | f    | 1998-09-11 | NULL  || Puffball | Diane | hamster | f    | 1999-03-30 | NULL  |+----------+-------+---------+------+------------+-------+

可以组合条件,例如,找出雌性的狗:

mysql> SELECT * FROM pet WHERE species = 'dog' AND sex = 'f';
+-------+--------+---------+------+------------+-------+| name  | owner  | species | sex  | birth      | death |+-------+--------+---------+------+------------+-------+| Buffy | Harold | dog     | f    | 1989-05-13 | NULL  |+-------+--------+---------+------+------------+-------+

上面的查询使用AND逻辑操作符,也有一个OR操作符:

mysql> SELECT * FROM pet WHERE species = 'snake' OR species = 'bird'; +----------+-------+---------+------+------------+-------+| name     | owner | species | sex  | birth      | death |+----------+-------+---------+------+------------+-------+| Chirpy   | Gwen  | bird    | f    | 1998-09-11 | NULL  || Whistler | Gwen  | bird    | NULL | 1997-12-09 | NULL  || Slim     | Benny | snake   | m    | 1996-04-29 | NULL  |+----------+-------+---------+------+------------+-------+

AND和OR可以混用,但AND比OR具有更高的优先级。如果你使用两个操作符,使用圆括号指明如何对条件进行分组是一个好主意:

mysql> SELECT * FROM pet WHERE (species = 'cat' AND sex = 'm')     -> OR (species = 'dog' AND sex = 'f'); +-------+--------+---------+------+------------+-------+| name  | owner  | species | sex  | birth      | death |+-------+--------+---------+------+------------+-------+| Claws | Gwen   | cat     | m    | 1994-03-17 | NULL  || Buffy | Harold | dog     | f    | 1989-05-13 | NULL  |+-------+--------+---------+------+------------+-------+

3. 选择特殊列

如果你不想看到表中的所有行,就命名你感兴趣的列,用逗号分开。例如,如果你想要知道你的动物什么时候出生的,选择name和birth列:

mysql> SELECT name, birth FROM pet; +----------+------------+| name     | birth      |+----------+------------+| Fluffy   | 1993-02-04 || Claws    | 1994-03-17 || Buffy    | 1989-05-13 || Fang     | 1990-08-27 || Bowser   | 1989-08-31 || Chirpy   | 1998-09-11 || Whistler | 1997-12-09 || Slim     | 1996-04-29 || Puffball | 1999-03-30 |+----------+------------+

找出谁拥有宠物,使用这个查询:

mysql> SELECT owner FROM pet; +--------+| owner  |+--------+| Harold || Gwen   || Harold || Benny  || Diane  || Gwen   || Gwen   || Benny  || Diane  |+--------+

请注意该查询只是简单地检索每个记录的owner列,并且他们中的一些出现多次。为了使输出减到最少,增加关键字DISTINCT检索出每个唯一的输出记录:

mysql> SELECT DISTINCT owner FROM pet; +--------+| owner  |+--------+| Benny  || Diane  || Gwen   || Harold |+--------+

可以使用一个WHERE子句结合行选择与列选择。例如,要想查询狗和猫的出生日期,使用这个查询:

mysql> SELECT name, species, birth FROM pet     -> WHERE species = 'dog' OR species = 'cat'; +--------+---------+------------+| name   | species | birth      |+--------+---------+------------+| Fluffy | cat     | 1993-02-04 || Claws  | cat     | 1994-03-17 || Buffy  | dog     | 1989-05-13 || Fang   | dog     | 1990-08-27 || Bowser | dog     | 1989-08-31 |+--------+---------+------------+

4. 分类行

你可能已经注意到前面的例子中结果行没有以特定的顺序显示。然而,当行按某种方式排序时,检查查询输出通常更容易。为了排序结果,使用ORDER BY子句。这里是动物生日,按日期排序:

mysql> SELECT name, birth FROM pet ORDER BY birth; +----------+------------+| name     | birth      |+----------+------------+| Buffy    | 1989-05-13 || Bowser   | 1989-08-31 || Fang     | 1990-08-27 || Fluffy   | 1993-02-04 || Claws    | 1994-03-17 || Slim     | 1996-04-29 || Whistler | 1997-12-09 || Chirpy   | 1998-09-11 || Puffball | 1999-03-30 |+----------+------------+

在字符类型列上,与所有其他比较操作类似,分类功能正常情况下是以区分大小写的方式执行的。这意味着,对于等同但大小写不同的列,并未定义其顺序。对于某一列,可以使用BINARY强制执行区分大小写的分类功能,如:ORDER BY BINARY col_name.

默认排序是升序,最小的值在第一。要想以降序排序,在你正在排序的列名上增加DESC(降序 )关键字:

mysql> SELECT name, birth FROM pet ORDER BY birth DESC; +----------+------------+| name     | birth      |+----------+------------+| Puffball | 1999-03-30 || Chirpy   | 1998-09-11 || Whistler | 1997-12-09 || Slim     | 1996-04-29 || Claws    | 1994-03-17 || Fluffy   | 1993-02-04 || Fang     | 1990-08-27 || Bowser   | 1989-08-31 || Buffy    | 1989-05-13 |+----------+------------+

可以对多个列进行排序,并且可以按不同的方向对不同的列进行排序。例如,按升序对动物的种类进行排序,然后按降序根据生日对各动物种类进行排序(最年轻的动物在最前面),使用下列查询:

mysql> SELECT name, species, birth FROM pet     -> ORDER BY species, birth DESC; +----------+---------+------------+| name     | species | birth      |+----------+---------+------------+| Chirpy   | bird    | 1998-09-11 || Whistler | bird    | 1997-12-09 || Claws    | cat     | 1994-03-17 || Fluffy   | cat     | 1993-02-04 || Fang     | dog     | 1990-08-27 || Bowser   | dog     | 1989-08-31 || Buffy    | dog     | 1989-05-13 || Puffball | hamster | 1999-03-30 || Slim     | snake   | 1996-04-29 |+----------+---------+------------+

注意DESC关键字仅适用于在它前面的列名(birth);不影响species列的排序顺序。

5. 日期计算

MySQL提供了几个函数,可以用来计算日期,例如,计算年龄或提取日期部分。

要想确定每个宠物有多大,可以计算当前日期的年和出生日期之间的差。如果当前日期的日历年比出生日期早,则减去一年。以下查询显示了每个宠物的出生日期、当前日期和年龄数值的年数字。

mysql> SELECT name, birth, CURDATE(),     -> (YEAR(CURDATE())-YEAR(birth))     -> - (RIGHT(CURDATE(),5) AS age     -> FROM pet; +----------+------------+------------+------+| name     | birth      | CURDATE()  | age  |+----------+------------+------------+------+| Fluffy   | 1993-02-04 | 2003-08-19 |   10 || Claws    | 1994-03-17 | 2003-08-19 |    9 || Buffy    | 1989-05-13 | 2003-08-19 |   14 || Fang     | 1990-08-27 | 2003-08-19 |   12 || Bowser   | 1989-08-31 | 2003-08-19 |   13 || Chirpy   | 1998-09-11 | 2003-08-19 |    4 || Whistler | 1997-12-09 | 2003-08-19 |    5 || Slim     | 1996-04-29 | 2003-08-19 |    7 || Puffball | 1999-03-30 | 2003-08-19 |    4 |+----------+------------+------------+------+

此处,YEAR()提取日期的年部分,RIGHT()提取日期的MM-DD (日历年)部分的最右面5个字符。比较MM-DD值的表达式部分的值一般为1或0,如果CURDATE()的年比birth的年早,则年份应减去1。整个表达式有些难懂,使用alias (age)来使输出的列标记更有意义。

尽管查询可行,如果以某个顺序排列行,则能更容易地浏览结果。添加ORDER BY name子句按照名字对输出进行排序则能够实现。

mysql> SELECT name, birth, CURDATE(),    -> (YEAR(CURDATE())-YEAR(birth))    -> - (RIGHT(CURDATE(),5) AS age

-> FROM pet ORDER BY name;

+----------+------------+------------+------+| name     | birth      | CURDATE()  | age  |+----------+------------+------------+------+| Bowser   | 1989-08-31 | 2003-08-19 |   13 || Buffy    | 1989-05-13 | 2003-08-19 |   14 || Chirpy   | 1998-09-11 | 2003-08-19 |    4 || Claws    | 1994-03-17 | 2003-08-19 |    9 || Fang     | 1990-08-27 | 2003-08-19 |   12 || Fluffy   | 1993-02-04 | 2003-08-19 |   10 || Puffball | 1999-03-30 | 2003-08-19 |    4 || Slim     | 1996-04-29 | 2003-08-19 |    7 || Whistler | 1997-12-09 | 2003-08-19 |    5 |+----------+------------+------------+------+

为了按age而非name排序输出,只要再使用一个ORDER BY子句:

mysql> SELECT name, birth, CURDATE(),     -> (YEAR(CURDATE())-YEAR(birth))     -> - (RIGHT(CURDATE(),5) AS age     -> FROM pet ORDER BY age; +----------+------------+------------+------+| name     | birth      | CURDATE()  | age  |+----------+------------+------------+------+| Chirpy   | 1998-09-11 | 2003-08-19 |    4 || Puffball | 1999-03-30 | 2003-08-19 |    4 || Whistler | 1997-12-09 | 2003-08-19 |    5 || Slim     | 1996-04-29 | 2003-08-19 |    7 || Claws    | 1994-03-17 | 2003-08-19 |    9 || Fluffy   | 1993-02-04 | 2003-08-19 |   10 || Fang     | 1990-08-27 | 2003-08-19 |   12 || Bowser   | 1989-08-31 | 2003-08-19 |   13 || Buffy    | 1989-05-13 | 2003-08-19 |   14 |+----------+------------+------------+------+

可以使用一个类似的查询来确定已经死亡动物的死亡年龄。你通过检查death值是否是NULL来确定是哪些动物,然后,对于那些非NULL值的动物,需要计算出death和birth值之间的差:

mysql> SELECT name, birth, death,     -> (YEAR(death)-YEAR(birth)) - (RIGHT(death,5) AS age     -> FROM pet WHERE death IS NOT NULL ORDER BY age; +--------+------------+------------+------+| name   | birth      | death      | age  |+--------+------------+------------+------+| Bowser | 1989-08-31 | 1995-07-29 |    5 |+--------+------------+------------+------+

查询使用death IS NOT NULL而非death != NULL,因为NULL是特殊的值,不能使用普通比较符来比较,以后会给出解释。

如果你想要知道哪个动物下个月过生日,怎么办?对于这类计算,年和天是无关的,你只需要提取birth列的月份部分。MySQL提供几个日期部分的提取函数,例如YEAR( )、MONTH( )和DAYOFMONTH( )。在这里MONTH()是适合的函数。为了看它怎样工作,运行一个简单的查询,显示birth和MONTH(birth)的值:

mysql> SELECT name, birth, MONTH(birth) FROM pet; +----------+------------+--------------+| name     | birth      | MONTH(birth) |+----------+------------+--------------+| Fluffy   | 1993-02-04 |            2 || Claws    | 1994-03-17 |            3 || Buffy    | 1989-05-13 |            5 || Fang     | 1990-08-27 |            8 || Bowser   | 1989-08-31 |            8 || Chirpy   | 1998-09-11 |            9 || Whistler | 1997-12-09 |           12 || Slim     | 1996-04-29 |            4 || Puffball | 1999-03-30 |            3 |+----------+------------+--------------+

找出下个月生日的动物也是容易的。假定当前月是4月,那么月值是4,你可以找在5月出生的动物 (5月),方法是:

mysql> SELECT name, birth FROM pet WHERE MONTH(birth) = 5; +-------+------------+| name  | birth      |+-------+------------+| Buffy | 1989-05-13 |+-------+------------+

如果当前月份是12月,就有点复杂了。你不能只把1加到月份数(12)上并寻找在13月出生的动物,因为没有这样的月份。相反,你应寻找在1月出生的动物(1月) 。

你甚至可以编写查询,不管当前月份是什么它都能工作。采用这种方法不必在查询中使用一个特定的月份,DATE_ADD( )允许在一个给定的日期上加上时间间隔。如果在NOW( )值上加上一个月,然后用MONTH()提取月份,结果产生生日所在月份:

mysql> SELECT name, birth FROM pet     -> WHERE MONTH(birth) = MONTH(DATE_ADD(CURDATE(),INTERVAL 1 MONTH));

完成该任务的另一个方法是加1以得出当前月份的下一个月(在使用取模函数(MOD)后,如果月份当前值是12,则“回滚”到值0):

mysql> 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)。

6. NULL值操作

NULL值可能令人感到奇怪直到你习惯它。概念上,NULL意味着“没有值”或“未知值”,且它被看作与众不同的值。为了测试NULL,你不能使用算术比较 操作符例如=、<或!=。为了说明它,试试下列查询:

mysql> SELECT 1 = NULL, 1  NULL, 1  NULL; +----------+-----------+----------+----------+| 1 = NULL | 1  NULL | 1  NULL |+----------+-----------+----------+----------+|     NULL |      NULL |     NULL |     NULL |+----------+-----------+----------+----------+

很显然你不能通过这些比较得到有意义的结果。相反使用IS NULL和IS NOT NULL操作符:

mysql> SELECT 1 IS NULL, 1 IS NOT NULL; +-----------+---------------+| 1 IS NULL | 1 IS NOT NULL |+-----------+---------------+|         0 |             1 |+-----------+---------------+

请注意在MySQL中,0或 NULL意味着假而其它值意味着真。布尔运算的默认真值是1。

对NULL的特殊处理即是在前面的章节中,为了决定哪个动物不再是活着的,使用death IS NOT NULL而不使用death != NULL的原因。

在GROUP BY中,两个NULL值视为相同。

执行ORDER BY时,如果运行 ORDER BY … ASC,则NULL值出现在最前面,若运行ORDER BY … DESC,则NULL值出现在最后面。

NULL操作的常见错误是不能在定义为NOT NULL的列内插入0或空字符串,但事实并非如此。在NULL表示”没有数值”的地方有数值。使用IS [NOT] NULL则可以很容易地进行测试,如下所示:

mysql> SELECT 0 IS NULL, 0 IS NOT NULL, '' IS NULL, '' IS NOT NULL; +-----------+---------------+------------+----------------+| 0 IS NULL | 0 IS NOT NULL | '' IS NULL | '' IS NOT NULL |+-----------+---------------+------------+----------------+|         0 |             1 |          0 |              1 |+-----------+---------------+------------+----------------+

因此完全可以在定义为NOT NULL的列内插入0或空字符串,实际是NOT NULL。

7. 模式匹配

MySQL提供标准的SQL模式匹配,以及一种基于象Unix实用程序如vigrepsed的扩展正则表达式模式匹配的格式。

SQL模式匹配允许你使用

“_”

匹配任何单个字符,而

“%”

匹配任意数目字符(包括零字符)。在 MySQL中,SQL的模式默认是忽略大小写的。下面给出一些例子。注意使用SQL模式时,不能使用=或!=;而应使用LIKE或NOT LIKE比较操作符。

要想找出以

“b”

开头的名字:

mysql> SELECT * FROM pet WHERE name LIKE 'b%'; +--------+--------+---------+------+------------+------------+| name   | owner  | species | sex  | birth      | death      |+--------+--------+---------+------+------------+------------+| Buffy  | Harold | dog     | f    | 1989-05-13 | NULL       || Bowser | Diane  | dog     | m    | 1989-08-31 | 1995-07-29 |+--------+--------+---------+------+------------+------------+

要想找出以

“fy”

结尾的名字:

mysql> SELECT * FROM pet WHERE name LIKE '%fy'; +--------+--------+---------+------+------------+-------+| name   | owner  | species | sex  | birth      | death |+--------+--------+---------+------+------------+-------+| Fluffy | Harold | cat     | f    | 1993-02-04 | NULL  || Buffy  | Harold | dog     | f    | 1989-05-13 | NULL  |+--------+--------+---------+------+------------+-------+

要想找出包含

“w”

的名字:

mysql> SELECT * FROM pet WHERE name LIKE '%w%'; +----------+-------+---------+------+------------+------------+| name     | owner | species | sex  | birth      | death      |+----------+-------+---------+------+------------+------------+| Claws    | Gwen  | cat     | m    | 1994-03-17 | NULL       || Bowser   | Diane | dog     | m    | 1989-08-31 | 1995-07-29 || Whistler | Gwen  | bird    | NULL | 1997-12-09 | NULL       |+----------+-------+---------+------+------------+------------+

要想找出正好包含5个字符的名字,使用

“_”

模式字符:

mysql> SELECT * FROM pet WHERE name LIKE '_____'; +-------+--------+---------+------+------------+-------+| name  | owner  | species | sex  | birth      | death |+-------+--------+---------+------+------------+-------+| Claws | Gwen   | cat     | m    | 1994-03-17 | NULL  || Buffy | Harold | dog     | f    | 1989-05-13 | NULL  |+-------+--------+---------+------+------------+-------+

MySQL提供的模式匹配的其它类型是使用扩展正则表达式。当你对这类模式进行匹配测试时,使用REGEXP和NOT REGEXP操作符(或RLIKE和NOT RLIKE,它们是同义词)。

扩展正则表达式的一些字符是:

·         ‘.’匹配任何单个的字符。

·         字符类

“[…]”

匹配在方括号内的任何字符。例如,

“[abc]”

匹配

“a”

“b”

小艺 小艺

华为公司推出的AI智能助手

小艺 549 查看详情 小艺

“c”

。为了命名字符的范围,使用一个“-”。

“[a-z]”

匹配任何字母,而

“[0-9]”

匹配任何数字。

·

“ * ”

匹配零个或多个在它前面的字符。例如,

“x*”

匹配任何数量的

“x”

字符,

“[0-9]*”

匹配任何数量的数字,而

“.*”

匹配任何数量的任何字符。

如果REGEXP模式与被测试值的任何地方匹配,模式就匹配(这不同于LIKE模式匹配,只有与整个值匹配,模式才匹配)。

为了定位一个模式以便它必须匹配被测试值的开始或结尾,在模式开始处使用
“^”

在模式的结尾用“$”

为了说明扩展正则表达式如何工作,下面使用REGEXP重写上面所示的LIKE查询:

为了找出以

“b”

开头的名字,使用

“^”

匹配名字的开始:

mysql> SELECT * FROM pet WHERE name REGEXP '^b'; +--------+--------+---------+------+------------+------------+| name   | owner  | species | sex  | birth      | death      |+--------+--------+---------+------+------------+------------+| Buffy  | Harold | dog     | f    | 1989-05-13 | NULL       || Bowser | Diane  | dog     | m    | 1989-08-31 | 1995-07-29 |+--------+--------+---------+------+------------+------------+

如果你想强制使REGEXP比较区分大小写,使用BINARY关键字使其中一个字符串变为二进制字符串。该查询只匹配名称首字母的小写‘b’。

mysql> SELECT * FROM pet WHERE name REGEXP BINARY '^b';

为了找出以

“fy”

结尾的名字,使用

“$”

匹配名字的结尾:

mysql> SELECT * FROM pet WHERE name REGEXP 'fy$'; +--------+--------+---------+------+------------+-------+| name   | owner  | species | sex  | birth      | death |+--------+--------+---------+------+------------+-------+| Fluffy | Harold | cat     | f    | 1993-02-04 | NULL  || Buffy  | Harold | dog     | f    | 1989-05-13 | NULL  |+--------+--------+---------+------+------------+-------+

为了找出包含一个

“w”

的名字,使用以下查询:

mysql> SELECT * FROM pet WHERE name REGEXP 'w'; +----------+-------+---------+------+------------+------------+| name     | owner | species | sex  | birth      | death      |+----------+-------+---------+------+------------+------------+| Claws    | Gwen  | cat     | m    | 1994-03-17 | NULL       || Bowser   | Diane | dog     | m    | 1989-08-31 | 1995-07-29 || Whistler | Gwen  | bird    | NULL | 1997-12-09 | NULL       |+----------+-------+---------+------+------------+------------+

既然如果一个正则表达式出现在值的任何地方,其模式匹配了,就不必在先前的查询中在模式的两侧放置一个通配符以使得它匹配整个值,就像你使用了一个SQL模式那样。

为了找出包含正好5个字符的名字,使用

“^”

“$”

匹配名字的开始和结尾,和5个

“.”

实例在两者之间:

mysql> SELECT * FROM pet WHERE name REGEXP '^.....$'; +-------+--------+---------+------+------------+-------+| name  | owner  | species | sex  | birth      | death |+-------+--------+---------+------+------------+-------+| Claws | Gwen   | cat     | m    | 1994-03-17 | NULL  || Buffy | Harold | dog     | f    | 1989-05-13 | NULL  |+-------+--------+---------+------+------------+-------+

你也可以使用

“{n}”

“重复n次”操作符重写前面的查询:

mysql> SELECT * FROM pet WHERE name REGEXP '^.{5}$'; +-------+--------+---------+------+------------+-------+| name  | owner  | species | sex  | birth      | death |+-------+--------+---------+------+------------+-------+| Claws | Gwen   | cat     | m    | 1994-03-17 | NULL  || Buffy | Harold | dog     | f    | 1989-05-13 | NULL  |+-------+--------+---------+------+------------+-------+

8. 计数行

数据库经常用于回答这个问题,“某个类型的数据在表中出现的频度?”例如,你可能想要知道你有多少宠物,或每位主人有多少宠物,或你可能想要对你的动物进行各种类型的普查。计算你拥有动物的总数目与“在pet表中有多少行?”是同样的问题,因为每个宠物有一个记录。COUNT(*)函数计算行数,所以计算动物数目的查询应为:

mysql> SELECT COUNT(*) FROM pet; +----------+| COUNT(*) |+----------+|        9 |+----------+

在前面,你检索了拥有宠物的人的名字。如果你想要知道每个主人有多少宠物,你可以使用COUNT( )函数:

mysql> SELECT owner, COUNT(*) FROM pet GROUP BY owner; +--------+----------+| owner  | COUNT(*) |+--------+----------+| Benny  |        2 || Diane  |        2 || Gwen   |        3 || Harold |        2 |+--------+----------+

注意,使用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; +---------+----------+| species | COUNT(*) |+---------+----------+| bird    |        2 || cat     |        2 || dog     |        3 || hamster |        1 || snake   |        1 |+---------+----------+

每种性别的动物数量:

mysql> SELECT sex, COUNT(*) FROM pet GROUP BY sex; +------+----------+| sex  | COUNT(*) |+------+----------+| NULL |        1 || f    |        4 || m    |        4 |+------+----------+

(在这个输出中,NULL表示“未知性别”。)

按种类和性别组合的动物数量:

mysql> SELECT species, sex, COUNT(*) FROM pet GROUP BY species, sex; +---------+------+----------+| species | sex  | COUNT(*) |+---------+------+----------+| bird    | NULL |        1 || bird    | f    |        1 || cat     | f    |        1 || cat     | m    |        1 || dog     | f    |        1 || dog     | m    |        2 || hamster | f    |        1 || snake   | m    |        1 |+---------+------+----------+

若使用COUNT( ),你不必检索整个表。例如, 前面的查询,当只对狗和猫进行时,应为:

mysql> SELECT species, sex, COUNT(*) FROM pet     -> WHERE species = 'dog' OR species = 'cat'     -> GROUP BY species, sex; +---------+------+----------+| species | sex  | COUNT(*) |+---------+------+----------+| cat     | f    |        1 || cat     | m    |        1 || dog     | f    |        1 || dog     | m    |        2 |+---------+------+----------+

或,如果你仅需要知道已知性别的按性别的动物数目:

mysql> SELECT species, sex, COUNT(*) FROM pet     -> WHERE sex IS NOT NULL     -> GROUP BY species, sex; +---------+------+----------+| species | sex  | COUNT(*) |+---------+------+----------+| bird    | f    |        1 || cat     | f    |        1 || cat     | m    |        1 || dog     | f    |        1 || dog     | m    |        2 || hamster | f    |        1 || snake   | m    |        1 |+---------+------+----------+

9. 使用1个以上的表

pet表追踪你有哪个宠物。如果你想要记录其它相关信息,例如在他们一生中看兽医或何时后代出生,你需要另外的表。这张表应该像什么呢?需要:·         它需要包含宠物名字以便你知道每个事件属于哪个动物。

·         需要一个日期以便你知道事件是什么时候发生的。

·         需要一个描述事件的字段。

·         如果你想要对事件进行分类,则需要一个事件类型字段。

综合上述因素,event表的CREATE TABLE语句应为:

mysql> CREATE TABLE event (name VARCHAR(20), date DATE,     -> type VARCHAR(15), remark VARCHAR(255));

对于pet表,最容易的方法是创建包含信息的用定位符分隔的文本文件来装载初始记录:

namedatetyperemarkFluffy1995-05-15litter4 kittens, 3 female, 1 maleBuffy1993-06-23litter5 puppies, 2 female, 3 maleBuffy1994-06-19litter3 puppies, 3 femaleChirpy1999-03-21vetneeded beak straightenedSlim1997-08-03vetbroken ribBowser1991-10-12kennel
Fang1991-10-12kennel
Fang1998-08-28birthdayGave him a new chew toyClaws1998-03-17birthdayGave him a new flea collarWhistler1998-12-09birthdayFirst birthday

采用如下方式装载记录:

mysql> LOAD DATA LOCAL INFILE 'event.txt' INTO TABLE event;

根据你从已经运行在pet表上的查询中学到的,你应该能执行对event表中记录的检索;原理是一样的。但是什么时候event表本身不能回答你可能问的问题呢?

当他们有了一窝小动物时,假定你想要找出每只宠物的年龄。我们前面看到了如何通过两个日期计算年龄。event表中有母亲的生产日期,但是为了计算母亲的年龄,你需要她的出生日期,存储在pet表中。说明查询需要两个表:

mysql> SELECT pet.name,     -> (YEAR(date)-YEAR(birth)) - (RIGHT(date,5) remark     -> FROM pet, event     -> WHERE pet.name = event.name AND event.type = 'litter'; +--------+------+-----------------------------+| name   | age  | remark                      |+--------+------+-----------------------------+| Fluffy |    2 | 4 kittens, 3 female, 1 male || Buffy  |    4 | 5 puppies, 2 female, 3 male || Buffy  |    5 | 3 puppies, 3 female         |+--------+------+-----------------------------+

关于该查询要注意的几件事情:

FROM子句列出两个表,因为查询需要从两个表提取信息。

当从多个表组合(联结)信息时,你需要指定一个表中的记录怎样能匹配其它表的记录。这很简单,因为它们都有一个name列。查询使用WHERE子句基于name值来匹配2个表中的记录。

因为name列出现在两个表中,当引用列时,你一定要指定哪个表。把表名附在列名前即可以实现。

你不必有2个不同的表来进行联结。如果你想要将一个表的记录与同一个表的其它记录进行比较,可以将一个表联结到自身。例如,为了在你的宠物之中繁殖配偶,你可以用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'; +--------+------+--------+------+---------+| name   | sex  | name   | sex  | species |+--------+------+--------+------+---------+| Fluffy | f    | Claws  | m    | cat     || Buffy  | f    | Fang   | m    | dog     || Buffy  | f    | Bowser | m    | dog     |+--------+------+--------+------+---------+

在这个查询中,我们为表名指定别名以便能引用列并且使得每一个列引用与哪个表实例相关联更直观。

 以上就是MySQL入门教程5 —— 从数据表中检索信息的内容,更多相关内容请关注PHP中文网(www.php.cn)! 

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 chuangxiangniao@163.com 举报,一经查实,本站将立刻删除。
发布者:程序猿,转转请注明出处:https://www.chuangxiangniao.com/p/800882.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
Cytoscape 安装教程 | Network Data Integration, Analysis, and Visualization in a Box
上一篇 2025年11月26日 18:01:10
不会编程自己怎么制作APP?
下一篇 2025年11月26日 18:01:13

相关推荐

  • 快手极速版官方网页版地址_快手极速版App下载官网首页

    快手极速版官方网页版地址在哪里?这是不少网友都关注的,接下来由PHP小编为大家带来快手极速版官方网页版地址及App下载相关信息,感兴趣的网友一起随小编来瞧瞧吧! https://www.kuaishou.com/ 1、小步骤内容。进入官网后可直接浏览平台首页推荐内容,涵盖生活记录、才艺展示等多个领域…

    2026年9月23日
    200
  • Flink项目实践 | Flink 单机安装部署

    Flink项目实践 | Flink 单机安装部署Flink项目实践 | Flink 单机安装部署Flink项目实践 | Flink 单机安装部署Flink项目实践 | Flink 单机安装部署

    apache flink 是一个用于对无界和有界数据流进行状态计算的框架和分布式处理引擎。flink 设计旨在所有常见集群环境中运行,并以内存速度和任意规模进行计算。 为了深入了解 Flink,首先需要搭建其运行环境。 Flink 可以在所有类似 UNIX 的环境中运行,包括 Linux,Mac O…

    2026年9月23日 用户投稿
    200
  • Windows系统安装MySQL的完整步骤是什么?

    Windows系统安装MySQL的完整步骤是什么?Windows系统安装MySQL的完整步骤是什么?Windows系统安装MySQL的完整步骤是什么?Windows系统安装MySQL的完整步骤是什么?

    安装#%#$#%@%@%$#%$#%#%#$%@_81c++3b080dad537de7e10e0987a4bf52e前需准备系统兼容性、硬件资源、前置运行时库、管理员权限及排查端口冲突。1. 系统兼容性:确保使用windows 10/11或对应server版本;2. 硬件资源:建议至少4gb内存;…

    2026年9月23日 用户投稿
    100
  • 如何在AdobeFresco导出AI生成的画作?快速保存图像的教程

    答案:Adobe Fresco支持PNG、JPG、PSD、PDF和MP4等导出格式。PNG适合透明背景和高质量网络展示;JPG适用于小文件、快速分享的有损压缩图像;PSD保留图层与矢量信息,便于在Photoshop中继续编辑;PDF适合打印和跨平台文档共享;MP4用于导出创作延时视频。选择格式时需根…

    2026年9月23日
    100
  • 优化 Laravel Nova 长耗时操作的响应消息持久化显示

    本文旨在解决 Laravel Nova 中耗时操作(如数分钟)的响应消息(Toast)短暂显示问题。针对默认 Action::message() 无法提供持久化反馈的局限性,我们将深入探讨如何利用 Laravel Nova 4 的通知功能,实现更持久、可交互且用户友好的操作完成提示,确保用户不会错过…

    2026年9月23日
    000
  • PHP三元运算符和if如何选_PHP三元运算符与if选择指南

    三元运算符适用于简单赋值或返回值,如条件赋值、模板输出;if语句适合复杂逻辑、多分支或多操作场景。性能差异可忽略,应优先考虑可读性和维护性。两者可结合使用,分工明确更清晰。 在PHP开发中,三元运算符和if语句都能实现条件判断,但它们适用的场景不同。选择合适的方式能让代码更清晰、易维护。关键不是“哪…

    2026年9月23日
    100
  • mysql怎么添加哈希索引 mysql创建哈希索引的使用场景

    mysql怎么添加哈希索引 mysql创建哈希索引的使用场景mysql怎么添加哈希索引 mysql创建哈希索引的使用场景mysql怎么添加哈希索引 mysql创建哈希索引的使用场景mysql怎么添加哈希索引 mysql创建哈希索引的使用场景

    mysql中可以显式添加哈希索引的场景仅限于memory存储引擎,1.创建memory表时通过using hash语法指定主键或辅助索引;2.对已有memory表使用alter table添加哈希索引。对于innodb等磁盘引擎,无法手动创建哈希索引,但其内部会自动管理自适应哈希索引(ahi)以优化…

    2026年9月23日 用户投稿
    000
  • VSCode配置MacOS C环境 详细图解VSCode搭建C++开发

    在mac++os上用vscode配置c/c++环境的关键是安装xcode command line tools以获取clang编译器和lldb调试器,然后安装vscode的c/c++扩展,接着创建项目文件夹和源文件,通过配置tasks.json定义编译任务,确保使用clang编译当前文件并生成可执行…

    2026年9月23日
    100
  • php数据如何防止CSRF跨站请求伪造_php数据表单令牌安全机制

    防止CSRF的核心是验证请求来源合法性,常用方法为表单令牌机制。1. 生成并存储CSRF令牌:用户访问表单页面时,PHP使用session_start()开启会话,通过bin2hex(random_bytes(32))生成安全令牌,存入$_SESSION[‘csrf_token&#821…

    2026年9月23日
    000
  • QQ阅读电子书官网_QQ阅读官方下载地址

    QQ阅读电子书官网是yuedu.reader.qq.com,该网站提供小说、杂志、漫画等多种数字内容,支持多设备同步与个性化阅读设置。 QQ阅读电子书官网地址在哪里?这是不少网友都关注的,接下来由PHP小编为大家带来QQ阅读电子书官网,感兴趣的网友一起随小编来瞧瞧吧! https://yuedu.3…

    2026年9月23日
    000
  • Snagit的AI工具怎么裁剪图片?教你精准完成图片裁剪方法

    Snagit的AI工具怎么裁剪图片?教你精准完成图片裁剪方法Snagit的AI工具怎么裁剪图片?教你精准完成图片裁剪方法Snagit的AI工具怎么裁剪图片?教你精准完成图片裁剪方法Snagit的AI工具怎么裁剪图片?教你精准完成图片裁剪方法

    Snagit虽无一键AI裁剪,但通过魔棒、智能移动等智能工具辅助选区,结合裁剪功能可高效精准裁剪;关键在于利用颜色识别与对象分离技术提升效率,避免纯手动操作,再通过调整比例、放大细节、善用撤销等功能优化结果。 ☞☞☞AI 智能聊天, 问答助手, AI 智能搜索, 免费无限量使用 DeepSeek R…

    2026年9月23日 用户投稿
    000
  • Java javac 命令与当前工作目录解析

    在Java编译环境中,javac命令的“当前目录”指的是命令被执行的物理位置,而非源文件所在的目录。理解这一概念对于正确配置和管理Java项目的编译路径至关重要,特别是当默认的classpath设置为.时,它决定了编译器查找类文件的起点。 1. javac 命令与当前工作目录的定义 在操作系统中,当…

    2026年9月23日
    100
  • 苹果 iPhone Air 今日正式发售:仅支持 eSIM,起售价 7999 元

    10 月 22 日消息,苹果全新 iphone air 于今日上午 8:00 正式开售,起售价定为 7999 元。值得关注的是,该机型仅支持 esim 功能,用户需持本人有效身份证件前往运营商实体营业厅完成实名核验与服务激活。现阶段仍处于商用试验阶段,暂未开放线上办理通道。 iPhone Air 搭…

    2026年9月23日
    200
  • VSCode调试JavaScript代码(详细图解,前端必学技能)

    掌握VSCode调试JavaScript需先安装Node.js和VSCode,创建项目及app.js文件后,配置launch.json,设置断点并启动调试,通过变量面板和控制台检查值,结合条件断点、日志点、监听表达式等技巧提升效率;调试浏览器代码需安装Chrome或Edge调试插件,配置url和we…

    2026年9月23日
    200
  • 配置php递归函数处理递归转换_通过php递归函数转换数据格式

    递归函数通过自我调用处理树形结构,需有终止条件和问题缩小机制;示例中将扁平数组按parent_id构建为嵌套树,反之亦可展平为带层级的列表,适用于菜单、分类等无限级数据操作。 在PHP开发中,经常需要处理树形结构数据,比如分类、菜单、评论嵌套等。这类数据通常具有父子关系,且层级不确定,这时就需要使用…

    2026年9月23日
    100
  • Bash Shell 中单引号和双引号的区别

    Bash Shell 中单引号和双引号的区别Bash Shell 中单引号和双引号的区别Bash Shell 中单引号和双引号的区别Bash Shell 中单引号和双引号的区别

    在 linux 命令行中,引号是处理文件名中的空格和特殊字符的常用工具。引号在 shell 脚本中具有“特殊功能”,可能让初学者感到困惑。让我们详细探讨不同类型的引号字符及其在 shell 脚本中的用法。 有四种不同类型的引号字符: 单引号 ‘双引号 “反斜杠 反引号 ` 除…

    2026年9月23日 用户投稿
    500
  • UC浏览器官方网页版登录入口 UC浏览器最新官网链接

    UC浏览器官方网页版登录入口在官网https://www.ucweb.com/,点击顶部“网页版”选项并登录账号即可使用。 UC浏览器官方网页版登录入口在哪里?这是不少网友都关注的,接下来由PHP小编为大家带来UC浏览器最新官网链接,想了解UC浏览器功能特点的网友一起随小编来瞧瞧吧! https:/…

    2026年9月23日
    700
  • Linux中如何查看服务日志?journalctl与syslog使用指南

    Linux中如何查看服务日志?journalctl与syslog使用指南Linux中如何查看服务日志?journalctl与syslog使用指南Linux中如何查看服务日志?journalctl与syslog使用指南Linux中如何查看服务日志?journalctl与syslog使用指南

    排查linux服务问题时,首选journalctl或syslog类系统查看日志。journalctl适用于systemd系统,可查看内核消息、服务启动输出等,支持按时间、单元、优先级过滤;syslog适用于传统系统,需服务主动发送日志,支持集中管理。掌握两者使用能有效定位问题。 在Linux系统中排…

    2026年9月23日 用户投稿
    100
  • Java语法基础中main方法为什么必须是public static void

    Main方法必须声明为public static void以确保JVM能无访问限制地通过类名直接调用,且不依赖对象实例或返回值,符合JVM规范对程序入口的强制要求。 Main方法是Java程序的入口点,它的标准声明形式为:public static void main(String[] args)。…

    2026年9月23日
    200
  • mysql安装后怎么授权 mysql用户权限设置操作教程

    mysql安装后怎么授权 mysql用户权限设置操作教程mysql安装后怎么授权 mysql用户权限设置操作教程mysql安装后怎么授权 mysql用户权限设置操作教程mysql安装后怎么授权 mysql用户权限设置操作教程

    创建用户并授权需用create user和grant命令,常见权限包括select、insert、update、delete、create、drop和all privileges,修改权限可用grant或revoke,设置时应注意作用范围、远程访问限制和密码安全。1. 创建用户使用create us…

    2026年9月23日 用户投稿
    1000

发表回复

登录后才能评论
关注微信