天天看点

【MySQL数据库开发之四】MySQL 处理模式/常用查询/模式匹配等(下)

“最大的物品号是什么?”

任务:找出最贵物品的编号、销售商和价格。这很容易用一个子查询做到:

另一个解决方案是按价格降序排序所有行并用MySQL特定LIMIT子句只得到第一行:

注:如果有多项最贵的物品( 例如每个的价格为19.95),LIMIT解决方案仅仅显示其中一个!

任务:每项物品的的最高价格是多少?

任务:对每项物品,找出最贵价格的物品的经销商。

可以用这样一个子查询解决该问题:

例如,要找出价格最高或最低的物品的,其方法是:

只是联接两个表时,不需要外部关键字。对于除InnoDB类型的表,当使用REFERENCES tbl_name(col_name)子句定义列时可以使用外部关键字,该子句没有实际的效果,只作为备忘录或注释来提醒,你目前正定义的列指向另一个表中的一个列。执行该语句时,实现下面很重要:

·         MySQL不执行表tbl_name 中的动作,例如作为你正定义的表中的行的动作的响应而删除行;换句话说,该句法不会致使ON DELETE或ON UPDATE行为(如果你在REFERENCES子句中写入ON DELETE或ON UPDATE子句,将被忽略)。

·         该句法可以创建一个column;但不创建任何索引或关键字。

·         如果用该句法定义InnoDB表,将会导致错误。

你可以使用作为联接列创建的列,如下所示:

CREATE TABLE person ( 

    id SMALLINT UNSIGNED NOT NULL AUTO_INCREMENT, 

    name CHAR(60) NOT NULL, 

    PRIMARY KEY (id) 

); 

CREATE TABLE shirt ( 

    style ENUM('t-shirt', 'polo', 'dress') NOT NULL, 

    color ENUM('red', 'blue', 'orange', 'white', 'black') NOT NULL, 

    owner SMALLINT UNSIGNED NOT NULL REFERENCES person(id), 

INSERT INTO person VALUES (NULL, 'Antonio Paz'); 

SELECT @last := LAST_INSERT_ID(); 

INSERT INTO shirt VALUES 

(NULL, 'polo', 'blue', @last), 

(NULL, 'dress', 'white', @last), 

(NULL, 't-shirt', 'blue', @last); 

INSERT INTO person VALUES (NULL, 'Lilliana Angelovska'); 

(NULL, 'dress', 'orange', @last), 

(NULL, 'polo', 'red', @last), 

(NULL, 'dress', 'blue', @last), 

(NULL, 't-shirt', 'white', @last); 

SELECT * FROM person; 

+----+---------------------+ 

| id | name                | 

|  1 | Antonio Paz         | 

|  2 | Lilliana Angelovska | 

SELECT * FROM shirt; 

+----+---------+--------+-------+ 

| id | style   | color  | owner | 

|  1 | polo    | blue   |     1 | 

|  2 | dress   | white  |     1 | 

|  3 | t-shirt | blue   |     1 | 

|  4 | dress   | orange |     2 | 

|  5 | polo    | red    |     2 | 

|  6 | dress   | blue   |     2 | 

|  7 | t-shirt | white  |     2 | 

SELECT s.* FROM person p, shirt s 

 WHERE p.name LIKE 'Lilliana%' 

   AND s.owner = p.id 

   AND s.color <> 'white'; 

+----+-------+--------+-------+ 

| id | style | color  | owner | 

|  4 | dress | orange |     2 | 

|  5 | polo  | red    |     2 | 

|  6 | dress | blue   |     2 | 

按照这种方式使用,REFERENCES子句不会显示在SHOW CREATE TABLE或DESCRIBE的输出中:

SHOW CREATE TABLE shirt\G 

*************************** 1. row *************************** 

Table: shirt 

Create Table: CREATE TABLE `shirt` ( 

`id` smallint(5) unsigned NOT NULL auto_increment, 

`style` enum('t-shirt','polo','dress') NOT NULL, 

`color` enum('red','blue','orange','white','black') NOT NULL, 

`owner` smallint(5) unsigned NOT NULL, 

PRIMARY KEY  (`id`) 

) ENGINE=MyISAM DEFAULT CHARSET=latin1 

在列定义中,按这种方式使用REFERENCES作为注释或“提示”适用于表MyISAM和BerkeleyDB。

一个比较灵活的例子是寻找两个通过OR组合到一起的关键字:

SELECT field1_index, field2_index FROM test_table 

WHERE field1_index = '1' OR  field2_index = '1' 

每个SELECT只搜索一个关键字,可以进行优化:

SELECT field1_index, field2_index 

    FROM test_table WHERE field1_index = '1' 

UNION 

    FROM test_table WHERE field2_index = '1'; 

CREATE TABLE t1 (year YEAR(4), month INT(2) UNSIGNED ZEROFILL, 

             day INT(2) UNSIGNED ZEROFILL); 

INSERT INTO t1 VALUES(2000,1,1),(2000,1,20),(2000,1,30),(2000,2,2), 

            (2000,2,23),(2000,2,23); 

示例表中含有代表用户访问网页的年-月-日值。可以使用以下查询来确定每个月的访问天数:

SELECT year,month,BIT_COUNT(BIT_OR(1<<day)) AS days FROM t1       GROUP BY year,month;

将返回:

+------+-------+------+ 

| year | month | days | 

| 2000 |    01 |    3 | 

| 2000 |    02 |    2 | 

该查询计算了在表中按年/月组合的不同天数,可以自动去除重复的询问。

CREATE TABLE animals ( 

     id MEDIUMINT NOT NULL AUTO_INCREMENT, 

     name CHAR(30) NOT NULL, 

     PRIMARY KEY (id) 

 ); 

INSERT INTO animals (name) VALUES 

    ('dog'),('cat'),('penguin'), 

    ('lax'),('whale'),('ostrich'); 

SELECT * FROM animals; 

+----+---------+ 

| id | name    | 

|  1 | dog     | 

|  2 | cat     | 

|  3 | penguin | 

|  4 | lax     | 

|  5 | whale   | 

|  6 | ostrich | 

你可以使用LAST_INSERT_ID()SQL函数或mysql_insert_id() C API函数来查询最新的AUTO_INCREMENT值。这些函数与具体连接有关,因此其返回值不会被其它执行插入功能的连接影响。

注释:对于多行插入,LAST_INSERT_ID()和mysql_insert_id()从插入的第一行实际返回AUTO_INCREMENT关键字。在复制设置中,通过该函数可以在其它服务器上正确复制多行插入。

对于MyISAM和BDB表,你可以在第二栏指定AUTO_INCREMENT以及多列索引。此时,AUTO_INCREMENT列生成的值的计算方法为:MAX(auto_increment_column) + 1 WHERE prefix=given-prefix。如果想要将数据放入到排序的组中可以使用该方法。

    grp ENUM('fish','mammal','bird') NOT NULL, 

    id MEDIUMINT NOT NULL AUTO_INCREMENT, 

    name CHAR(30) NOT NULL, 

    PRIMARY KEY (grp,id) 

INSERT INTO animals (grp,name) VALUES 

    ('mammal','dog'),('mammal','cat'), 

    ('bird','penguin'),('fish','lax'),('mammal','whale'), 

    ('bird','ostrich'); 

SELECT * FROM animals ORDER BY grp,id; 

+--------+----+---------+ 

| grp    | id | name    | 

| fish   |  1 | lax     | 

| mammal |  1 | dog     | 

| mammal |  2 | cat     | 

| mammal |  3 | whale   | 

| bird   |  1 | penguin | 

| bird   |  2 | ostrich | 

请注意在这种情况下(AUTO_INCREMENT列是多列索引的一部分),如果你在任何组中删除有最大AUTO_INCREMENT值的行,将会重新用到AUTO_INCREMENT值。对于MyISAM表也如此,对于该表一般不重复使用AUTO_INCREMENT值。

如果AUTO_INCREMENT列是多索引的一部分,MySQL将使用该索引生成以AUTO_INCREMENT列开始的序列值。。例如,如果animals表含有索引PRIMARY KEY (grp, id)和INDEX(id),MySQL生成序列值时将忽略PRIMARY KEY。结果是,该表包含一个单个的序列,而不是符合grp值的序列。

要想以AUTO_INCREMENT值开始而不是1,你可以通过CREATE TABLE或ALTER TABLE来设置该值,如下所示:

关于AUTO_INCREMENT的详细信息:

本文转自 xiaominghimi 51CTO博客,原文链接:http://blog.51cto.com/xiaominghimi/908931,如需转载请自行联系原作者