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

相关推荐

  • composer require-dev和require有什么不同_Composer Require与Require-Dev区别解析

    require用于声明项目运行必需的依赖,如框架、数据库组件和第三方SDK,这些包会随项目部署到生产环境;2. require-dev用于声明仅在开发和测试阶段需要的工具,如PHPUnit、PHPStan、Faker等,不会默认部署到生产环境;3. 安装时composer install根据环境决定…

    2026年5月10日
    1000
  • 开源免费PHP工具 PHP开发效率提升利器

    推荐开源免费PHP开发工具以提升效率:VS Code、Sublime Text轻量高效,PhpStorm专业强大;调试用Xdebug、Kint、Ray;依赖管理选Composer;代码质量工具包括PHPStan、Psalm、PHP_CodeSniffer;数据库管理可用%ignore_a_1%MyA…

    2026年5月10日
    000
  • Golang JSON序列化:控制敏感字段暴露的最佳实践

    本教程探讨golang中如何高效控制结构体字段在json序列化时的可见性。当需要将包含敏感信息的结构体数组转换为json响应时,通过利用`encoding/json`包提供的结构体标签,特别是`json:”-“`,可以轻松实现对特定字段的忽略,从而避免敏感数据泄露,确保api…

    2026年5月10日
    000
  • 怎么在PHP代码中实现图片上传功能_PHP图片上传功能实现与安全处理教程

    首先创建含enctype的HTML表单,再用PHP接收文件,检查目录、移动临时文件,验证类型与大小,生成唯一文件名,并调整php.ini限制以确保上传成功。 如果您尝试在PHP项目中添加图片上传功能,但服务器无法正确接收或保存文件,则可能是由于表单配置、文件处理逻辑或安全限制的问题。以下是实现该功能…

    2026年5月10日
    100
  • 获取日期中的周数:CodeIgniter 教程

    本教程旨在帮助开发者在 CodeIgniter 框架中,从日期字符串中准确提取周数。我们将使用 PHP 内置的 DateTime 类,并提供详细的代码示例和注意事项,确保您能够轻松地在项目中实现此功能。 使用 DateTime 类获取周数 PHP 的 DateTime 类提供了一种便捷的方式来处理日…

    2026年5月10日
    100
  • 比特币新手教程 比特币交易平台有哪些

    比特币是一种去中心化的数字货币,基于区块链技术实现点对点交易,具有匿名性、有限发行和不可篡改等特点;新手可通过交易所购买,P2P交易获得比特币,常用平台包括Binance、OKX和Huobi;交易流程包括注册账户、实名认证、绑定支付方式、充值法币并下单购买,可选择市价单或限价单;比特币存储方式有交易…

    2026年5月10日
    000
  • c++中的SFINAE技术是什么_c++模板编程中的SFINAE原理与应用

    SFINAE 是“替换失败不是错误”的原则,指模板实例化时若参数替换导致错误,只要存在其他合法候选,编译器不报错而是继续重载决议。它用于条件启用模板、类型检测等场景,如通过 decltype 或 enable_if 控制函数重载,实现类型特征判断。尽管 C++20 引入 Concepts 简化了部分…

    2026年5月10日
    000
  • Go语言mgo查询构建:深入理解bson.M与日期范围查询的正确实践

    本文旨在解决go语言mgo库中构建复杂查询时,特别是涉及嵌套`bson.m`和日期范围筛选的常见错误。我们将深入剖析`bson.m`的类型特性,解释为何直接索引`interface{}`会导致“invalid operation”错误,并提供一种推荐的、结构清晰的代码重构方案,以确保查询条件能够正确…

    2026年5月10日
    100
  • Golang goroutine与channel调试技巧

    使用go run -race检测数据竞争,结合runtime.NumGoroutine监控协程数量,通过pprof分析阻塞调用栈,利用select超时避免永久阻塞,有效排查goroutine泄漏、死锁和数据竞争问题。 Go语言的goroutine和channel是并发编程的核心,但它们也带来了调试上…

    2026年5月10日
    000
  • 使用 Jupyter Notebook 进行探索性数据分析

    Jupyter Notebook通过单元格实现代码与Markdown结合,支持数据导入(pandas)、清洗(fillna)、探索(matplotlib/seaborn可视化)、统计分析(describe/corr)和特征工程,便于记录与分享分析过程。 Jupyter Notebook 是进行探索性…

    2026年5月10日
    000
  • 《魔兽世界》将于6月11日开启国服回归技术测试

    《魔兽世界》将于6月11日开启国服回归技术测试《魔兽世界》将于6月11日开启国服回归技术测试《魔兽世界》将于6月11日开启国服回归技术测试《魔兽世界》将于6月11日开启国服回归技术测试

    《%ign%ignore_a_1%re_a_1%》官方宣布,将于6月11日开启国服回归技术测试,时间为7天,并称可以在6月内正式开服,玩家们可以访问官网下载战网客户端并预下载“巫妖王之怒”客户端,技术测试详情见下图。 WordAi WordAI是一个AI驱动的内容重写平台 53 查看详情 以上就是《…

    2026年5月10日 用户投稿
    200
  • php常量怎么用_PHP常量(define/const)定义与使用方法

    PHP中可通过define函数和const关键字定义常量,用于存储不可变值。define适用于全局作用域,支持动态名称和条件定义,如define(‘SITE_NAME’, ‘MyWebsite’);const在编译时生效,语法简洁但限制多,只能在类或全…

    2026年5月10日
    000
  • 如何在HTML中插入表单元素_HTML表单控件与输入类型使用指南

    HTML表单通过标签构建,包含action和method属性定义数据提交目标与方式,常用input类型如text、password、email等适配不同输入需求,配合label、required、placeholder提升可用性,结合textarea、select、button等控件实现完整交互,是…

    2026年5月10日
    100
  • 创建指定大小并填充特定数据的Golang文件教程

    本文将介绍如何使用Golang创建一个指定大小的文件,并用特定数据填充它。我们将使用 `os` 包提供的函数来创建和截断文件,从而实现快速生成大文件的目的。示例代码展示了如何创建一个10MB的文件,并将其填充为全零数据。掌握这些方法,可以方便地在例如日志系统或磁盘队列等场景中,预先创建测试文件或初始…

    2026年5月10日
    000
  • Python命令怎样使用profile分析脚本性能 Python命令性能分析的基础教程

    使用Python的cProfile模块分析脚本性能最直接的方式是通过命令行执行python -m cProfile your_script.py,它会输出每个函数的调用次数、总耗时、累积耗时等关键指标,帮助定位性能瓶颈;为进一步分析,可将结果保存为文件python -m cProfile -o ou…

    2026年5月10日
    000
  • 如何插入查询结果数据_SQL插入Select查询结果方法

    如何插入查询结果数据_SQL插入Select查询结果方法如何插入查询结果数据_SQL插入Select查询结果方法如何插入查询结果数据_SQL插入Select查询结果方法如何插入查询结果数据_SQL插入Select查询结果方法

    使用INSERT INTO…SELECT语句可高效插入数据,通过NOT EXISTS、LEFT JOIN、MERGE语句或唯一约束避免重复;表结构不一致时可通过别名、类型转换、默认值或计算字段处理;结合存储过程可提升可维护性,支持参数化与动态SQL。 将查询结果数据插入到另一个表中,可以…

    2026年5月10日 用户投稿
    000
  • 使用 WebCodecs VideoDecoder 实现精确逐帧回退

    本文档旨在解决在使用 WebCodecs VideoDecoder 进行视频解码时,实现精确逐帧回退的问题。通过比较帧的时间戳与目标帧的时间戳,可以避免渲染中间帧,从而提高用户体验。本文将提供详细的解决方案和示例代码,帮助开发者实现精确的视频帧控制。 在使用 WebCodecs VideoDecod…

    2026年5月10日
    000
  • PHP动态生成表单输入与POST数据获取实践指南

    本教程详细阐述了如何在php中根据动态数据源(如数据库值)生成多个表单输入框,并演示了如何通过post方法准确无误地获取这些动态生成的输入值。文章强调了正确的输入框命名策略,避免了常见的命名误区,并提供了完整的代码示例,确保开发者能够高效处理动态表单数据。 动态生成表单输入 在Web开发中,我们经常…

    2026年5月10日
    000
  • Discord.py 交互按钮超时与持久化解决方案

    本教程旨在解决Discord.py中交互按钮在一段时间后出现“This Interaction Failed”错误的问题。我们将深入探讨视图(View)的超时机制,并提供通过正确设置timeout参数以及利用bot.add_view()方法实现按钮持久化的具体方案,确保您的机器人交互功能稳定可靠,即…

    2026年5月10日
    000
  • Debian Copilot的社区活跃度如何

    debian copilot是codeberg社区维护的ai助手,旨在为debian用户提供服务。尽管搜索结果中没有直接提供关于debian copilot社区支持活跃度的具体数据,但我们可以通过debian社区的整体活跃度和特点来推断其活跃性。 Debian社区的一般情况: Debian拥有详尽的…

    2026年5月10日
    000

发表回复

登录后才能评论
关注微信