MySQL Cookbook 学习笔记-03

1、INNER JOIN关联查询
2、outer join(LEFT JOIN 与 RIGHT JOIN)
3、自连接
4、主从表查询
5、在分组内查找某列最大或最小的一行
6、计算小组积分榜
7、计算连续行的差
8、计算“累计和”与运行时平均值
9、使用 JOIN 控制查询结果的顺序
10、通过 UNION 合并查询结果集

———————————————————————————————————————————

1、INNER JOIN关联查询

(Recipe 12.1. Finding Rows in One Table That Match Rows in Another)

CREATE TABLE artist
(a_id  INT UNSIGNED NOT NULL AUTO_INCREMENT, # artist IDname  VARCHAR(30) NOT NULL,                 # artist namePRIMARY KEY (a_id),UNIQUE (name)
);CREATE TABLE painting
(a_id  INT UNSIGNED NOT NULL,                # artist IDp_id  INT UNSIGNED NOT NULL AUTO_INCREMENT, # painting IDtitle VARCHAR(100) NOT NULL,                # title of paintingstate VARCHAR(2) NOT NULL,                  # state where purchasedprice INT UNSIGNED,                         # purchase price (dollars)INDEX (a_id),PRIMARY KEY (p_id)
);

表的数据:

mysql> SELECT * FROM artist ORDER BY a_id;
+------+----------+
| a_id | name     |
+------+----------+
|    1 | Da Vinci |
|    2 | Monet    |
|    3 | Van Gogh |
|    4 | Picasso  |
|    5 | Renoir   |
+------+----------+
mysql> SELECT * FROM painting ORDER BY a_id, p_id;
+------+------+-------------------+-------+-------+
| a_id | p_id | title             | state | price |
+------+------+-------------------+-------+-------+
|    1 |    1 | The Last Supper   | IN    |    34 |
|    1 |    2 | The Mona Lisa     | MI    |    87 |
|    3 |    3 | Starry Night      | KY    |    48 |
|    3 |    4 | The Potato Eaters | KY    |    67 |
|    3 |    5 | The Rocks         | IA    |    33 |
|    5 |    6 | Les Deux Soeurs   | NE    |    64 |
+------+------+-------------------+-------+-------+
方案一:通过 where 语句关联查询

mysql> SELECT * FROM artist, painting-> WHERE artist.a_id = painting.a_id;
方案二:通过 INNER JOIN .... ON 关联查询(等价方案一)

mysql> SELECT * FROM artist INNER JOIN painting-> ON artist.a_id = painting.a_id;
+------+----------+------+------+-------------------+-------+-------+
| a_id | name     | a_id | p_id | title             | state | price |
+------+----------+------+------+-------------------+-------+-------+
|    1 | Da Vinci |    1 |    1 | The Last Supper   | IN    |    34 |
|    1 | Da Vinci |    1 |    2 | The Mona Lisa     | MI    |    87 |
|    3 | Van Gogh |    3 |    3 | Starry Night      | KY    |    48 |
|    3 | Van Gogh |    3 |    4 | The Potato Eaters | KY    |    67 |
|    3 | Van Gogh |    3 |    5 | The Rocks         | IA    |    33 |
|    5 | Renoir   |    5 |    6 | Les Deux Soeurs   | NE    |    64 |
+------+----------+------+------+-------------------+-------+-------+
方案三:通过 INNER JOIN ... USING 关联查询(关联两表的列必须相同)

mysql> SELECT * FROM artist INNER JOIN painting-> USING(a_id);
+------+----------+------+-------------------+-------+-------+
| a_id | name     | p_id | title             | state | price |
+------+----------+------+-------------------+-------+-------+
|    1 | Da Vinci |    1 | The Last Supper   | IN    |    34 |
|    1 | Da Vinci |    2 | The Mona Lisa     | MI    |    87 |
|    3 | Van Gogh |    3 | Starry Night      | KY    |    48 |
|    3 | Van Gogh |    4 | The Potato Eaters | KY    |    67 |
|    3 | Van Gogh |    5 | The Rocks         | IA    |    33 |
|    5 | Renoir   |    6 | Les Deux Soeurs   | NE    |    64 |
+------+----------+------+-------------------+-------+-------+
推荐用法:JOIN 语句来关联表,where 子句作为筛选条件

mysql> SELECT artist.name, painting.title, painting.state, painting.price-> FROM artist INNER JOIN painting-> ON artist.a_id = painting.a_id-> WHERE painting.state = 'KY';
+----------+-------------------+-------+-------+
| name     | title             | state | price |
+----------+-------------------+-------+-------+
| Van Gogh | Starry Night      | KY    |    48 |
| Van Gogh | The Potato Eaters | KY    |    67 |
+----------+-------------------+-------+-------+
三表关联示例:

mysql> SELECT artist.name, painting.title, states.name, painting.price-> FROM artist INNER JOIN painting INNER JOIN states-> ON artist.a_id = painting.a_id AND painting.state = states.abbrev;
+----------+-------------------+----------+-------+
| name     | title             | name     | price |
+----------+-------------------+----------+-------+
| Da Vinci | The Last Supper   | Indiana  |    34 |
| Da Vinci | The Mona Lisa     | Michigan |    87 |
| Van Gogh | Starry Night      | Kentucky |    48 |
| Van Gogh | The Potato Eaters | Kentucky |    67 |
| Van Gogh | The Rocks         | Iowa     |    33 |
| Renoir   | Les Deux Soeurs   | Nebraska |    64 |
+----------+-------------------+----------+-------+
关联查询和聚合函数——示例

mysql> SELECT artist.name,-> COUNT(*) AS 'number of paintings',-> SUM(painting.price) AS 'total price',-> AVG(painting.price) AS 'average price'-> FROM artist INNER JOIN painting ON artist.a_id = painting.a_id-> GROUP BY artist.name;
+----------+---------------------+-------------+---------------+
| name     | number of paintings | total price | average price |
+----------+---------------------+-------------+---------------+
| Da Vinci |                   2 |         121 |       60.5000 |
| Renoir   |                   1 |          64 |       64.0000 |
| Van Gogh |                   3 |         148 |       49.3333 |
+----------+---------------------+-------------+---------------+
特别注意:为了提高联合查询的效率,一般将联合的列(如:a_id)设定为索引!

TABLE artist,a_id 为主键(强制索引)

TABLE painting,a_id 直接设定为索引


2、outer join(LEFT JOIN 与 RIGHT JOIN)

查询在表painting 中没有作品的作者:

mysql> select artist.a_id, artist.name from artist-> left join painting on artist.a_id = painting.a_id-> where painting.a_id is null;
+------+---------+
| a_id | name    |
+------+---------+
|    2 | Monet   |
|    4 | Picasso |
+------+---------+
其它方法(非 JOIN)

mysql> select artist.a_id, artist.name from artist-> where artist.a_id not in (-> select painting.a_id from painting-> );
+------+---------+
| a_id | name    |
+------+---------+
|    2 | Monet   |
|    4 | Picasso |
+------+---------+
LEFT JOIN 和 RIGHT JOIN 的相互转换:

mysql> SELECT artist.name,-> IF(COUNT(painting.a_id)>0,'yes','no') AS 'in collection'-> FROM artist LEFT JOIN painting ON artist.a_id = painting.a_id-> GROUP BY artist.name;
+----------+---------------+
| name     | in collection |
+----------+---------------+
| Da Vinci | yes           |
| Monet    | no            |
| Picasso  | no            |
| Renoir   | yes           |
| Van Gogh | yes           |
+----------+---------------+
mysql> SELECT artist.name,-> IF(COUNT(painting.a_id)>0,'yes','no') AS 'in collection'-> FROM painting RIGHT JOIN artist ON artist.a_id = painting.a_id-> GROUP BY artist.name;
+----------+---------------+
| name     | in collection |
+----------+---------------+
| Da Vinci | yes           |
| Monet    | no            |
| Picasso  | no            |
| Renoir   | yes           |
| Van Gogh | yes           |
+----------+---------------+

3、自连接

任务:查找作品为“The Potato Eaters”的作者的所有作品。

mysql> select p2.title-> from painting as p1 inner join painting as p2-> on p1.a_id = p2.a_id-> where p1.title = 'The Potato Eaters';
+-------------------+
| title             |
+-------------------+
| Starry Night      |
| The Potato Eaters |
| The Rocks         |
+-------------------+
替换方法(嵌套查询)

mysql> select title from painting-> where painting.a_id = (-> select a_id from painting where title = 'The Potato Eaters'-> );
+-------------------+
| title             |
+-------------------+
| Starry Night      |
| The Potato Eaters |
| The Rocks         |
+-------------------+

4、主从表查询

a、只查询从表中有数据的“主-从”关联查询,用 INNER  JOIN

b、查询主表中所有数据,从表可以没有,用 LEFT  JOIN

a——示例

mysql> select artist.name, painting.title-> from artist INNER JOIN painting ON artist.a_id = painting.a_id-> order by name, title;
+----------+-------------------+
| name     | title             |
+----------+-------------------+
| Da Vinci | The Last Supper   |
| Da Vinci | The Mona Lisa     |
| Renoir   | Les Deux Soeurs   |
| Van Gogh | Starry Night      |
| Van Gogh | The Potato Eaters |
| Van Gogh | The Rocks         |
+----------+-------------------+

带聚集函数——示例

mysql> select artist.name as painter, count(painting.a_id) as count-> from artist INNER JOIN painting ON artist.a_id = painting.a_id-> group by artist.name;
+----------+-------+
| painter  | count |
+----------+-------+
| Da Vinci |     2 |
| Renoir   |     1 |
| Van Gogh |     3 |
+----------+-------+

b——示例

mysql> select artist.name, painting.title-> from artist LEFT JOIN painting ON artist.a_id = painting.a_id-> order by name, title;
+----------+-------------------+
| name     | title             |
+----------+-------------------+
| Da Vinci | The Last Supper   |
| Da Vinci | The Mona Lisa     |
| Monet    | NULL              |
| Picasso  | NULL              |
| Renoir   | Les Deux Soeurs   |
| Van Gogh | Starry Night      |
| Van Gogh | The Potato Eaters |
| Van Gogh | The Rocks         |
+----------+-------------------+
带聚集函数——示例

mysql> select a.a_id, a.name, p.a_id, count(p.a_id) as count-> from artist as a LEFT JOIN painting as p ON a.a_id = p.a_id-> group by a.name;
+------+----------+------+-------+
| a_id | name     | a_id | count |
+------+----------+------+-------+
|    1 | Da Vinci |    1 |     2 |
|    2 | Monet    | NULL |     0 |
|    4 | Picasso  | NULL |     0 |
|    5 | Renoir   |    5 |     1 |
|    3 | Van Gogh |    3 |     3 |
+------+----------+------+-------+
聚集函数会忽略 NULL 值,count( ) 会将 NULL 值操作返回0!

例如:

mysql> select * from taxpayer;
+---------+--------+
| name    | id     |
+---------+--------+
| bernina | 198-48 |
| bertha  | NULL   |
| ben     | NULL   |
| NULL    | 475-83 |
| baidu   | 111+55 |
+---------+--------+mysql> select count(id) from taxpayer-> where name='ben';
+-----------+
| count(id) |
+-----------+
|         0 |
+-----------+
其他聚集函数(如,SUM( ),AVG( ))就必须做特殊处理:

mysql> select a.name as painter,-> count(p.a_id) as 'number of paintings',-> sum(p.price) as 'total price',-> avg(p.price) as 'average price'-> from artist as a LEFT JOIN painting as p ON a.a_id = p.a_id-> group by a.name;
+----------+---------------------+-------------+---------------+
| painter  | number of paintings | total price | average price |
+----------+---------------------+-------------+---------------+
| Da Vinci |                   2 |         121 |       60.5000 |
| Monet    |                   0 |        NULL |          NULL |
| Picasso  |                   0 |        NULL |          NULL |
| Renoir   |                   1 |          64 |       64.0000 |
| Van Gogh |                   3 |         148 |       49.3333 |
+----------+---------------------+-------------+---------------+
这里的 SUM( ) 和 AVG( )函数返回的都为 NULL ,显然不合理,修改如下:

mysql> select a.name as painter,-> count(p.a_id) as 'number of paintings',-> IFNULL(sum(p.price),0) as 'total price',-> IFNULL(avg(p.price),0) as 'average price'-> from artist as a LEFT JOIN painting as p ON a.a_id = p.a_id-> group by a.name;
+----------+---------------------+-------------+---------------+
| painter  | number of paintings | total price | average price |
+----------+---------------------+-------------+---------------+
| Da Vinci |                   2 |         121 |       60.5000 |
| Monet    |                   0 |           0 |        0.0000 |
| Picasso  |                   0 |           0 |        0.0000 |
| Renoir   |                   1 |          64 |       64.0000 |
| Van Gogh |                   3 |         148 |       49.3333 |
+----------+---------------------+-------------+---------------+

5、在分组内查找某列最大或最小的一行

(Recipe 12.6. Finding Rows Containing Per-Group Minimum or Maximum Values)

查找全表某列最大或最小的行,如下方法合适:

mysql> select a.name, p.title, p.price-> from artist as a INNER JOIN painting as p-> ON p.a_id = a.a_id-> where p.price = (select max(price) from painting);
+----------+---------------+-------+
| name     | title         | price |
+----------+---------------+-------+
| Da Vinci | The Mona Lisa |    87 |
+----------+---------------+-------+
查找 分组内某列最大或最小的行, 错误方法( 我的):
mysql> select a.name, p.title, max(p.price)-> from artist as a INNER JOIN painting as p-> ON a.a_id = p.a_id-> group by a.name;
+----------+-----------------+--------------+
| name     | title           | max(p.price) |
+----------+-----------------+--------------+
| Da Vinci | The Last Supper |           87 |
| Renoir   | Les Deux Soeurs |           64 |
| Van Gogh | Starry Night    |           67 |
+----------+-----------------+--------------+
分析原因,看两表连接查询数据:

mysql> select a.name, p.title, p.price-> from artist as a INNER JOIN painting as p-> ON a.a_id = p.a_id;
+----------+-------------------+-------+
| name     | title             | price |
+----------+-------------------+-------+
| Da Vinci | The Last Supper   |    34 |
| Da Vinci | The Mona Lisa     |    87 |
| Renoir   | Les Deux Soeurs   |    64 |
| Van Gogh | Starry Night      |    48 |
| Van Gogh | The Potato Eaters |    67 |
| Van Gogh | The Rocks         |    33 |
+----------+-------------------+-------+
总结:虽然 我的方法中“name”列和“max(price)”列都是正确的,但是“title”列却是任意的!
正确方法:

a、单独创建临时表,与临时表关联查询

b、同过 FROM 子句连接查询

c、通过自连接连接查询(比较难懂)

a——示例

mysql> create table tmp-> select a_id, max(price) as max_price from painting group by a_id;//演示用-START
mysql> select * from tmp;
+------+-----------+
| a_id | max_price |
+------+-----------+
|    1 |        87 |
|    3 |        67 |
|    5 |        64 |
+------+-----------+
//演示用-ENDmysql> select a.name, p.title, p.price-> from artist as a INNER JOIN painting as p INNER JOIN tmp as t-> ON a.a_id = p.a_id-> AND p.a_id = t.a_id-> AND p.price = t.max_price;
+----------+-------------------+-------+
| name     | title             | price |
+----------+-------------------+-------+
| Da Vinci | The Mona Lisa     |    87 |
| Van Gogh | The Potato Eaters |    67 |
| Renoir   | Les Deux Soeurs   |    64 |
+----------+-------------------+-------+
b——示例

mysql> select a.name, p.title, p.price-> from artist as a INNER JOIN painting as p-> INNER JOIN (select a_id, max(price) as max_price from painting group by a_id) as tmp-> ON a.a_id = p.a_id-> AND p.a_id = tmp.a_id-> AND p.price = tmp.max_price;
+----------+-------------------+-------+
| name     | title             | price |
+----------+-------------------+-------+
| Da Vinci | The Mona Lisa     |    87 |
| Van Gogh | The Potato Eaters |    67 |
| Renoir   | Les Deux Soeurs   |    64 |
+----------+-------------------+-------+
c——示例

mysql> select a.name, p1.title, p1.price-> from painting as p1 LEFT JOIN painting as p2-> ON p1.a_id = p2.a_id-> AND p1.price < p2.price-> INNER JOIN artist as a-> ON p1.a_id = a.a_id-> WHERE p2.a_id is null;
+----------+-------------------+-------+
| name     | title             | price |
+----------+-------------------+-------+
| Da Vinci | The Mona Lisa     |    87 |
| Renoir   | Les Deux Soeurs   |    64 |
| Van Gogh | The Potato Eaters |    67 |
+----------+-------------------+-------+

6、计算小组积分榜

(Recipe 12.7. Computing Team Standings)

如下数据:

mysql> SELECT team, wins, losses FROM standings1-> ORDER BY wins-losses DESC;
+-------------+------+--------+
| team        | wins | losses |
+-------------+------+--------+
| Winnipeg    |   37 |     20 |
| Crookston   |   31 |     25 |
| Fargo       |   30 |     26 |
| Grand Forks |   28 |     26 |
| Devils Lake |   19 |     31 |
| Cavalier    |   15 |     32 |
+-------------+------+--------+
计算获胜的比例公式: wins / (wins + losses)

为了预防还没有一场比赛的情况,公式增强改为:IF( wins=0, 0, wins/(wins+losses) )

Game Behind 公式:( (winsA - lossesA) - (winsB - lossesB) ) / 2

给定一个小组(其实就是“Winnipeg”小组)作为比较的基准:

mysql> SET @wl_diff = (SELECT MAX(wins-losses) FROM standings1);
查询计算结果为:

mysql> SELECT team, wins AS W, losses AS L,-> wins/(wins+losses) AS PCT,-> (@wl_diff - (wins-losses)) / 2 AS GB-> FROM standings1-> ORDER BY wins-losses DESC, PCT DESC;
+-------------+------+------+--------+---------+
| team        | W    | L    | PCT    | GB      |
+-------------+------+------+--------+---------+
| Winnipeg    |   37 |   20 | 0.6491 |  0.0000 |
| Crookston   |   31 |   25 | 0.5536 |  5.5000 |
| Fargo       |   30 |   26 | 0.5357 |  6.5000 |
| Grand Forks |   28 |   26 | 0.5185 |  7.5000 |
| Devils Lake |   19 |   31 | 0.3800 | 14.5000 |
| Cavalier    |   15 |   32 | 0.3191 | 17.0000 |
+-------------+------+------+--------+---------+
改进:

mysql> SELECT team, wins AS W, losses AS L,-> TRUNCATE(wins/(wins+losses),3) AS PCT,-> IF(@wl_diff = wins-losses,->    '-',TRUNCATE((@wl_diff - (wins-losses))/2,1)) AS GB-> FROM standings1-> ORDER BY wins-losses DESC, PCT DESC;
+-------------+------+------+-------+------+
| team        | W    | L    | PCT   | GB   |
+-------------+------+------+-------+------+
| Winnipeg    |   37 |   20 | 0.649 | -    |
| Crookston   |   31 |   25 | 0.553 | 5.5  |
| Fargo       |   30 |   26 | 0.535 | 6.5  |
| Grand Forks |   28 |   26 | 0.518 | 7.5  |
| Devils Lake |   19 |   31 | 0.380 | 14.5 |
| Cavalier    |   15 |   32 | 0.319 | 17.0 |
+-------------+------+------+-------+------+

7、计算连续行的差

(Recipe 12.9. Calculating Successive-Row Differences)

mysql> SELECT seq, city, miles FROM trip_log ORDER BY seq;
+-----+------------------+-------+
| seq | city             | miles |
+-----+------------------+-------+
|   1 | San Antonio, TX  |     0 |
|   2 | Dallas, TX       |   263 |
|   3 | Benton, AR       |   566 |
|   4 | Memphis, TN      |   745 |
|   5 | Portageville, MO |   878 |
|   6 | Champaign, IL    |  1164 |
|   7 | Madison, WI      |  1412 |
+-----+------------------+-------+
计算连续两城市的距离( dist):

mysql> SELECT t1.seq AS seq1, t2.seq AS seq2,-> t1.city AS city1, t2.city AS city2,-> t1.miles AS miles1, t2.miles AS miles2,-> t2.miles-t1.miles AS dist-> FROM trip_log AS t1 INNER JOIN trip_log AS t2-> ON t1.seq+1 = t2.seq-> ORDER BY t1.seq;
+------+------+------------------+------------------+--------+--------+------+
| seq1 | seq2 | city1            | city2            | miles1 | miles2 | dist |
+------+------+------------------+------------------+--------+--------+------+
|    1 |    2 | San Antonio, TX  | Dallas, TX       |      0 |    263 |  263 |
|    2 |    3 | Dallas, TX       | Benton, AR       |    263 |    566 |  303 |
|    3 |    4 | Benton, AR       | Memphis, TN      |    566 |    745 |  179 |
|    4 |    5 | Memphis, TN      | Portageville, MO |    745 |    878 |  133 |
|    5 |    6 | Portageville, MO | Champaign, IL    |    878 |   1164 |  286 |
|    6 |    7 | Champaign, IL    | Madison, WI      |   1164 |   1412 |  248 |
+------+------+------------------+------------------+--------+--------+------+

8、计算“累计和”与运行时平均值

(Recipe 12.10. Finding Cumulative Sums and Running Averages)

mysql> SELECT date, precip FROM rainfall ORDER BY date;
+------------+--------+
| date       | precip |
+------------+--------+
| 2006-06-01 |   1.50 |
| 2006-06-02 |   0.00 |
| 2006-06-03 |   0.50 |
| 2006-06-04 |   0.00 |
| 2006-06-05 |   1.00 |
+------------+--------+
计算每天的累计降雨量( 自连接):

mysql> SELECT t1.date, t1.precip AS 'daily precip',-> SUM(t2.precip) AS 'cum. precip'-> FROM rainfall AS t1 INNER JOIN rainfall AS t2-> ON t1.date >= t2.date-> GROUP BY t1.date;
+------------+--------------+-------------+
| date       | daily precip | cum. precip |
+------------+--------------+-------------+
| 2006-06-01 |         1.50 |        1.50 |
| 2006-06-02 |         0.00 |        1.50 |
| 2006-06-03 |         0.50 |        2.00 |
| 2006-06-04 |         0.00 |        2.00 |
| 2006-06-05 |         1.00 |        3.00 |
+------------+--------------+-------------+
一般化:

mysql> SELECT t1.date, t1.precip AS 'daily precip',-> SUM(t2.precip) AS 'cum. precip',-> COUNT(t2.precip) AS 'days elapsed',-> AVG(t2.precip) AS 'avg. precip'-> FROM rainfall AS t1 INNER JOIN rainfall AS t2-> ON t1.date >= t2.date-> GROUP BY t1.date;
+------------+--------------+-------------+--------------+-------------+
| date       | daily precip | cum. precip | days elapsed | avg. precip |
+------------+--------------+-------------+--------------+-------------+
| 2006-06-01 |         1.50 |        1.50 |            1 |    1.500000 |
| 2006-06-02 |         0.00 |        1.50 |            2 |    0.750000 |
| 2006-06-03 |         0.50 |        2.00 |            3 |    0.666667 |
| 2006-06-04 |         0.00 |        2.00 |            4 |    0.500000 |
| 2006-06-05 |         1.00 |        3.00 |            5 |    0.600000 |
+------------+--------------+-------------+--------------+-------------+
如果日期不连续呢(如,删除“precip”的值为 0 ,的行)

mysql> DELETE FROM rainfall WHERE precip = 0;
mysql> SELECT date, precip FROM rainfall ORDER BY date;
+------------+--------+
| date       | precip |
+------------+--------+
| 2006-06-01 |   1.50 |
| 2006-06-03 |   0.50 |
| 2006-06-05 |   1.00 |
+------------+--------+
计算累计天数 =  DATEDIFF( MAX(t2.date), MIN(t2.date) ) + 1

计算平均降雨量 = 总的降雨量 / 累计天数

mysql> SELECT t1.date, t1.precip AS 'daily precip',-> SUM(t2.precip) AS 'cum. precip',-> DATEDIFF(MAX(t2.date),MIN(t2.date)) + 1 AS 'days elapsed',-> SUM(t2.precip) / (DATEDIFF(MAX(t2.date),MIN(t2.date)) + 1)-> AS 'avg. precip'-> FROM rainfall AS t1 INNER JOIN rainfall AS t2-> ON t1.date >= t2.date-> GROUP BY t1.date;
+------------+--------------+-------------+--------------+-------------+
| date       | daily precip | cum. precip | days elapsed | avg. precip |
+------------+--------------+-------------+--------------+-------------+
| 2006-06-01 |         1.50 |        1.50 |            1 |    1.500000 |
| 2006-06-03 |         0.50 |        2.00 |            3 |    0.666667 |
| 2006-06-05 |         1.00 |        3.00 |            5 |    0.600000 |
+------------+--------------+-------------+--------------+-------------+
另一例(对时间的特殊处理)

mysql> SELECT stage, km, t FROM marathon ORDER BY stage;
+-------+----+----------+
| stage | km | t        |
+-------+----+----------+
|     1 |  5 | 00:15:00 |
|     2 |  7 | 00:19:30 |
|     3 |  9 | 00:29:20 |
|     4 |  5 | 00:17:50 |
+-------+----+----------+
mysql> SELECT t1.stage, t1.km, t1.t,-> SUM(t2.km) AS 'cum. km',-> SEC_TO_TIME(SUM(TIME_TO_SEC(t2.t))) AS 'cum. t',-> SUM(t2.km)/(SUM(TIME_TO_SEC(t2.t))/(60*60)) AS 'avg. km/hour'-> FROM marathon AS t1 INNER JOIN marathon AS t2-> ON t1.stage >= t2.stage-> GROUP BY t1.stage;
+-------+----+----------+---------+----------+--------------+
| stage | km | t        | cum. km | cum. t   | avg. km/hour |
+-------+----+----------+---------+----------+--------------+
|     1 |  5 | 00:15:00 |       5 | 00:15:00 |      20.0000 |
|     2 |  7 | 00:19:30 |      12 | 00:34:30 |      20.8696 |
|     3 |  9 | 00:29:20 |      21 | 01:03:50 |      19.7389 |
|     4 |  5 | 00:17:50 |      26 | 01:21:40 |      19.1020 |
+-------+----+----------+---------+----------+--------------+

9、使用 JOIN 控制查询结果的顺序

(Recipe 12.11. Using a Join to Control Query Output Order)

a、创建一个辅助表,然后连接查询

b、使用 FROM 子句连接查询

数据如下:

mysql> SELECT * FROM driver_log ORDER BY rec_id;
+--------+-------+------------+-------+
| rec_id | name  | trav_date  | miles |
+--------+-------+------------+-------+
|      1 | Ben   | 2006-08-30 |   152 |
|      2 | Suzi  | 2006-08-29 |   391 |
|      3 | Henry | 2006-08-29 |   300 |
|      4 | Henry | 2006-08-27 |    96 |
|      5 | Ben   | 2006-08-29 |   131 |
|      6 | Henry | 2006-08-26 |   115 |
|      7 | Suzi  | 2006-09-02 |   502 |
|      8 | Henry | 2006-09-01 |   197 |
|      9 | Ben   | 2006-09-02 |    79 |
|     10 | Henry | 2006-08-30 |   203 |
+--------+-------+------------+-------+
任务:统计出每个人的总里程,并按总里程从大到小排序

a——示例

mysql> CREATE TABLE tmp-> SELECT name, SUM(miles) AS driver_miles FROM driver_log GROUP BY name;//演示——START
mysql> SELECT * FROM tmp ORDER BY driver_miles DESC;
+-------+--------------+
| name  | driver_miles |
+-------+--------------+
| Henry |          911 |
| Suzi  |          893 |
| Ben   |          362 |
+-------+--------------+
//演示——ENDmysql> SELECT tmp.driver_miles, driver_log.*-> FROM driver_log INNER JOIN tmp-> ON driver_log.name = tmp.name-> ORDER BY tmp.driver_miles DESC, driver_log.trav_date;
+--------------+--------+-------+------------+-------+
| driver_miles | rec_id | name  | trav_date  | miles |
+--------------+--------+-------+------------+-------+
|          911 |      6 | Henry | 2006-08-26 |   115 |
|          911 |      4 | Henry | 2006-08-27 |    96 |
|          911 |      3 | Henry | 2006-08-29 |   300 |
|          911 |     10 | Henry | 2006-08-30 |   203 |
|          911 |      8 | Henry | 2006-09-01 |   197 |
|          893 |      2 | Suzi  | 2006-08-29 |   391 |
|          893 |      7 | Suzi  | 2006-09-02 |   502 |
|          362 |      5 | Ben   | 2006-08-29 |   131 |
|          362 |      1 | Ben   | 2006-08-30 |   152 |
|          362 |      9 | Ben   | 2006-09-02 |    79 |
+--------------+--------+-------+------------+-------+
b——示例

mysql> SELECT tmp.driver_miles, driver_log.*-> FROM driver_log INNER JOIN-> (SELECT name, SUM(miles) AS driver_miles FROM driver_log GROUP BY name) AS tmp-> ON driver_log.name = tmp.name-> ORDER BY tmp.driver_miles DESC, driver_log.trav_date;
+--------------+--------+-------+------------+-------+
| driver_miles | rec_id | name  | trav_date  | miles |
+--------------+--------+-------+------------+-------+
|          911 |      6 | Henry | 2006-08-26 |   115 |
|          911 |      4 | Henry | 2006-08-27 |    96 |
|          911 |      3 | Henry | 2006-08-29 |   300 |
|          911 |     10 | Henry | 2006-08-30 |   203 |
|          911 |      8 | Henry | 2006-09-01 |   197 |
|          893 |      2 | Suzi  | 2006-08-29 |   391 |
|          893 |      7 | Suzi  | 2006-09-02 |   502 |
|          362 |      5 | Ben   | 2006-08-29 |   131 |
|          362 |      1 | Ben   | 2006-08-30 |   152 |
|          362 |      9 | Ben   | 2006-09-02 |    79 |
+--------------+--------+-------+------------+-------+

10、通过 UNION 合并查询结果集

(Recipe 12.12. Combining Several Result Sets in a Single Query)

UNION,删除重复的行

UNION ALL,不删除重复的行

演示数据:

mysql> SELECT * FROM prospect;
+---------+-------+------------------------+
| fname   | lname | addr                   |
+---------+-------+------------------------+
| Peter   | Jones | 482 Rush St., Apt. 402 |
| Bernice | Smith | 916 Maple Dr.          |
+---------+-------+------------------------+
mysql> SELECT * FROM customer;
+-----------+------------+---------------------+
| last_name | first_name | address             |
+-----------+------------+---------------------+
| Peterson  | Grace      | 16055 Seminole Ave. |
| Smith     | Bernice    | 916 Maple Dr.       |
| Brown     | Walter     | 8602 1st St.        |
+-----------+------------+---------------------+
mysql> SELECT * FROM vendor;
+-------------------+---------------------+
| company           | street              |
+-------------------+---------------------+
| ReddyParts, Inc.  | 38 Industrial Blvd. |
| Parts-to-go, Ltd. | 213B Commerce Park. |
+-------------------+---------------------+
UNION——演示

mysql> SELECT fname, lname, addr FROM prospect-> UNION-> SELECT first_name, last_name, address FROM customer-> UNION-> SELECT company, '', street FROM vendor;
+-------------------+----------+------------------------+
| fname             | lname    | addr                   |
+-------------------+----------+------------------------+
| Peter             | Jones    | 482 Rush St., Apt. 402 |
| Bernice           | Smith    | 916 Maple Dr.          |
| Grace             | Peterson | 16055 Seminole Ave.    |
| Walter            | Brown    | 8602 1st St.           |
| ReddyParts, Inc.  |          | 38 Industrial Blvd.    |
| Parts-to-go, Ltd. |          | 213B Commerce Park.    |
+-------------------+----------+------------------------+
UNION ALL——演示

mysql> SELECT fname, lname, addr FROM prospect-> UNION ALL-> SELECT first_name, last_name, address FROM customer-> UNION ALL-> SELECT company, '', street FROM vendor;
+-------------------+----------+------------------------+
| fname             | lname    | addr                   |
+-------------------+----------+------------------------+
| Peter             | Jones    | 482 Rush St., Apt. 402 |
| Bernice           | Smith    | 916 Maple Dr.          |
| Grace             | Peterson | 16055 Seminole Ave.    |
| Bernice           | Smith    | 916 Maple Dr.          |
| Walter            | Brown    | 8602 1st St.           |
| ReddyParts, Inc.  |          | 38 Industrial Blvd.    |
| Parts-to-go, Ltd. |          | 213B Commerce Park.    |
+-------------------+----------+------------------------+
列的合并处理:

mysql> (SELECT CONCAT(lname,', ',fname) AS name, addr FROM prospect)-> UNION-> (SELECT CONCAT(last_name,', ',first_name), address FROM customer)-> UNION-> (SELECT company, street FROM vendor)-> ORDER BY name;
+-------------------+------------------------+
| name              | addr                   |
+-------------------+------------------------+
| Brown, Walter     | 8602 1st St.           |
| Jones, Peter      | 482 Rush St., Apt. 402 |
| Parts-to-go, Ltd. | 213B Commerce Park.    |
| Peterson, Grace   | 16055 Seminole Ave.    |
| ReddyParts, Inc.  | 38 Industrial Blvd.    |
| Smith, Bernice    | 916 Maple Dr.          |
+-------------------+------------------------+

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/498109.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

数据可视化--pyecharts绘图

pyecharts 是一个用于生成 Echarts 图表的类库。 Echarts 是百度开源的一个数据可视化 JS 库。主要用于数据可视化。 要使用pyecharts绘制地图&#xff0c;首先需要安装一下几个地图模块&#xff1a; 1、安装地图数据包&#xff0c;用于显示地图 pip install echarts-countri…

echart x轴标签偏移_1文搞懂真正的五轴加工中心,到底说的5轴是哪几个轴

随着国内数控技术的日渐成熟&#xff0c;近年来五轴联动数控加工中心在各领域得到了越来越广泛的应用。在实际应用中&#xff0c;每当人们碰见异形复杂零件高效、高质量加工难题时&#xff0c;五轴联动技术无疑是解决这类问题的重要手段。越来越多的厂家倾向于寻找五轴设备来满…

中国在国际上首次提出全液态量子器件与计算技术概念

来源&#xff1a;人民日报 概要&#xff1a;液态金属可以用来制造计算机核心电子元件&#xff0c;进而引发计算机的革命&#xff1f; 液态金属可以用来制造计算机核心电子元件&#xff0c;进而引发计算机的革命&#xff1f;不久前&#xff0c;我国一个研究小组发表了一项成果&…

MySQL Cookbook 学习笔记-04

1、处理重复 <a>、创建表包含 primary key 或 unique index&#xff0c;阻止重复数据写入 <b>、联合 <a>&#xff0c;使用 INSERT IGNORE 或 REPLACE <c>、检查表是否有重复行的方法&#xff0c;通过 group by 和 count( x ) 来统计 <d>、通…

如何使用frame框架,将左边视为导航栏,右边作为链接界面

在浏览网页时&#xff0c;我们经常会看到一个导航条&#xff0c;当点击导航条上的项目时&#xff0c;相应网页会在显示区域变换显示。那么如何将一个界面中&#xff0c;左边设置为导航栏&#xff0c;点击项目链接&#xff0c;则右边显示相应的内容呢&#xff1f;使用frameset框…

面对大规模AI集成,企业为何迟迟犹豫?

来源&#xff1a;亿欧 概要&#xff1a;首先&#xff0c;需要全面了解您的业务目标、技术需求以及AI对客户和员工的影响。需要解决的问题是&#xff0c;大多数员工面临着接受人工智能程度方面的挑战与担忧。 人工智能是实现流程自动化、降低运营成本和进创新的重要手段。尽管AI…

类的初始化

加载 ----> 连接&#xff08;验证&#xff0c;准备&#xff0c;解析*&#xff09; ---->初始化 Java 虚拟机在首次主动使用类型时初始化它们。 主动使用&#xff08;6种&#xff09; 1、创建类的实例 2、调用类中声明的静态方法 3、操作类或者接口中声明的非常量静态…

用定时器控制灯的闪烁梯形图_用西门子PLC设计灯的闪烁的梯形图,就只要梯形图。...

展开全部使用特32313133353236313431303231363533e58685e5aeb931333431373235殊标志寄存器即可实现你想要的功能&#xff0c;如果想要设计出亮的时间固定、灭的时间也固定的闪烁效果比较复杂。SM0.5 该位提供了一个时钟脉冲&#xff0c;0.5 秒为1&#xff0c;0.5 秒为0&#xf…

如何进行模糊分页

使用模糊分页需要3个参数:关键字&#xff1a;key,当前页&#xff1a;page,查询内容个数&#xff1a;count 核心代码&#xff1a; //所有菜单列表分页private void foodList(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException …

PostgreSQL+安装及常见问题

postgresql-8.1-int.msi postgresql-8.1.msi &#xff08;点这个安装&#xff09; 前面一直用默认 1、到如下画面时注意&#xff1a; 重复账户时&#xff0c;报如下错误&#xff1a; 2、勾选所有连接都能使用该PostgreSQL 数据库&#xff0c;而不是仅仅支持 Localhost 3、…

post和get请求的区别

1.传送方式&#xff1a;get通过地址栏传输&#xff0c;post通过报文传输。 2.post请求无长度限制&#xff08;至少是理论上的&#xff09; &#xff1b;get有长度限制&#xff0c;最长不超过2048字节&#xff08;1024个汉字&#xff09; 3.Get/post 请求报文上的区别 get 和…

js 操作vuex数据_vue中使用vuex(超详细)

vuex是使用vue中必不可少的一部分,基于父子、兄弟组件,我们传值可能会很方便,但是如果是没有关联的组件之间要使用同一组数据,就显得很无能为力,那么vuex就很好的解决了我们这种问题,它相当于一个公共仓库,保存着所有组件都能共用的数据。 那么,我们一起来看看vue项目怎…

用脑科学支持人工智能

来源&#xff1a;中国科学报 概要&#xff1a;脑科学研究者正在揭示预测性运动控制神经机制&#xff0c;以脑科学基础研究支持人工智能发展并促进两大领域的深度融合。 最近&#xff0c;在国家自然科学基金&#xff08;项目号&#xff1a;31671075&#xff09;的支持下&#x…

mysql数据库进行更新、插入显示中文乱码问题

很多种情况下&#xff0c;从数据库中查询出来的内容中文显示正确&#xff0c;但是如果向数据库中插入或更新表时&#xff0c;会出现中文乱码问题&#xff0c;但英文显示正确&#xff0c;以下三种方式可以解决中文乱码问题。 1.数据库连接的配置文件中添加characterEncodingutf…

1进程 ppid_杀死僵尸进程,你需要这些神奇的Linux命令行

Linux高手&#xff0c;其实都是玩儿命令行很熟练的人。命令行的学习捷径Linux命令有许多强大的功能&#xff1a;从简单的磁盘操作、文件存取&#xff0c;到进行复杂的多媒体图像和流媒体文件的制作&#xff0c;都离不开命令行。在Linux的学习中&#xff0c;新手都会遇到这么一个…

PostgreSQL 常见操作

1、在命令行登录指定数据库 2、创建表 CREATE TABLE weather (city varchar(80),temp_lo int, -- low temperaturetemp_hi int, -- high temperatureprcp real, -- precipitationdate date ); …

大数据统计分析毕业设计_数据分析毕业设计 大数据可视化毕业设计

做大数据分析相关的毕业设计&#xff0c;有什么好的题目或方向推荐吗&#xff1f;毛台九大数据其它九大数据油业&#xff0c;三农&#xff0c;科研&#xff0c;人文&#xff0c;……打算用Python做毕业设计&#xff0c;可以做哪些方面的&#xff1f;Python做毕业设计&#xff0…

MultipartFile文件上传

一、配置文件&#xff1a; SpringMVC 用的是 的MultipartFile来进行文件上传 所以我们首先要配置MultipartResolver:用于处理表单中的file。在springmvc.xml中进行配置&#xff0c;目录结构如下&#xff1a; <!-- 配置MultipartResolver 用于文件上传 使用spring的CommosMul…

一个简单的 iBatis 实现——完整示例

表和数据&#xff1a; CREATE TABLE weather (city varchar(80),temp_lo int, -- low temperaturetemp_hi int, -- high temperatureprcp real, -- average temperaturedate date );insert int…