跳转至

MYSQL操作4-----复杂查询

1.连表查询

Ⅰ. 连表查询即查询的结果来自多张表

Ⅱ. 连表查询的分类

内连接:又称为等值连接

外连接

左外连接:以左表为依据让右表进行连接。左表的数据会全部显示,右表与左表相同的数据显示,不同的数据使用null填充。

右外连接:以右表为依据让左表进行连接。右表的数据会全部显示,左表与右表相同的数据显示,不同的数据使用null填充。

完全外连接:左右外连接的数据合并到一起。

Ⅲ. 语句

内连接:

select * from 表1 inner join 表2 on 表1.列表=表2.列表

左连接:

select * from 表1 left join 表2 on 表1.列表=表2.列表

右连接:

select * from 表1 right join 表2 on 表1.列表=表2.列表

案例:

a. 建表

mysql> use school;
Database changed
mysql> select database();
+------------+
| database() |
+------------+
| school     |
+------------+
1 row in set (0.00 sec)

mysql> show tables;
Empty set (0.00 sec)

mysql> create table A(姓名 char(10),毕业院校 char(20));
Query OK, 0 rows affected (0.01 sec)

mysql> create table B(姓名 char(10),职业 char(20));
Query OK, 0 rows affected (0.00 sec)

mysql> insert into A values('杨过','哈工大'),('郭靖','北大'),('黄蓉','武大'),('风清扬','西交大');
Query OK, 4 rows affected (0.01 sec)
Records: 4  Duplicates: 0  Warnings: 0

mysql> insert into B (姓名,职业) values('杨过','作家'),('杨逍','演员'),('孙杨','运动员'),('黄蓉','考研');
Query OK, 4 rows affected (0.00 sec)
Records: 4  Duplicates: 0  Warnings: 0

查询A表中毕业院校及职业

b. 分析

查询毕业院校和职业。

毕业院校来自于A表,职业来自于B表,所以需要连表查询。

语句写法:表名卸载join两边,on后跟连接依据(表中相同值的列表)

操作:

mysql> select A.姓名,毕业院校,职业 from A inner join B on A.姓名=B.姓名;   #或
mysql> select * from A inner join B on A.姓名=B.姓名;
+--------+--------------+--------+
| 姓名   | 毕业院校     | 职业   |
+--------+--------------+--------+
| 杨过   | 哈工大       | 作家   |
| 黄蓉   | 武大         | 考研   |
+--------+--------------+--------+
2 rows in set (0.00 sec)

mysql> select * from A left join B on A.姓名=B.姓名;
+-----------+--------------+--------+--------+
| 姓名      | 毕业院校     | 姓名   | 职业   |
+-----------+--------------+--------+--------+
| 杨过      | 哈工大       | 杨过   | 作家   |
| 郭靖      | 北大         | NULL   | NULL   |
| 黄蓉      | 武大         | 黄蓉   | 考研   |
| 风清扬    | 西交大       | NULL   | NULL   |
+-----------+--------------+--------+--------+
4 rows in set (0.00 sec)

mysql> select * from A right join B on A.姓名=B.姓名;
+--------+--------------+--------+-----------+
| 姓名   | 毕业院校     | 姓名   | 职业      |
+--------+--------------+--------+-----------+
| 杨过   | 哈工大       | 杨过   | 作家      |
| NULL   | NULL         | 杨逍   | 演员      |
| NULL   | NULL         | 孙杨   | 运动员    |
| 黄蓉   | 武大         | 黄蓉   | 考研      |
+--------+--------------+--------+-----------+
4 rows in set (0.00 sec)

Ⅳ. 三张表相连

表1 ---------------- 表2 ---------------- 表3

列名X ----- 列名X 列名Y ----- 列名Y

SELECT 字段列表 FROM

表1 INNER JOIN 表2 ON 表1.列名X=表2.列名X

INNER JOIN 表3 ON 表2.列名Y=表3.列名Y

准备案例:

导入word.sql。world库中有三张表city、country、countrylanguage

city表的结结构:

  • name:城市名称

  • countrycode:国家代码

  • District:省、州

  • population:人口数量

country表的结构:

  • code:国家代码

  • name:国家名

  • Continet:大洲名

  • surfacearea:国土面积

Ⅴ. 分组查询

语法:

select * from 表名 [where 条件] group by 分组依据 [having 条件]

案例:

a. 统计city表中中国每个省的城市数量

mysql> select district,count(*) from city where countrycode='CHN' group by District;
+----------------+----------+
| district       | count(*) |
+----------------+----------+
| Shanghai       |        1 |
| Peking         |        2 |
| Chongqing      |        1 |
| Tianjin        |        1 |
| Hubei          |       22 |
| Heilongjiang   |       21 |
| Liaoning       |       21 |
| Guangdong      |       20 |
| Sichuan        |       21 |
| Jiangsu        |       25 |
| Jilin          |       20 |
| Shaanxi        |        8 |
| Shandong       |       32 |
| Zhejiang       |       16 |
| Henan          |       18 |
| Hebei          |       12 |
| Shanxi         |        9 |
| Yunnan         |        5 |
| Hunan          |       18 |
| Jiangxi        |       11 |
| Fujian         |       12 |
| Gansu          |        7 |
| Guizhou        |        6 |
| Anhui          |       16 |
| Xinxiang       |       10 |
| Guangxi        |        9 |
| Inner Mongolia |       13 |
| Qinghai        |        1 |
| Ningxia        |        2 |
| Hainan         |        2 |
| Tibet          |        1 |
+----------------+----------+
31 rows in set (0.01 sec)

b. 统计city表中中国每个省的人口数量

mysql> SELECT district,SUM(population) FROM city WHERE countrycode='CHN' GROUP BY district;
+----------------+-----------------+
| district       | SUM(population) |
+----------------+-----------------+
| Shanghai       |         9696300 |
| Peking         |         7569168 |
| Chongqing      |         6351600 |
| Tianjin        |         5286800 |
| Hubei          |         8547585 |
| Heilongjiang   |        11628057 |
| Liaoning       |        15079174 |
| Guangdong      |         9510263 |
| Sichuan        |         7456867 |
| Jiangsu        |         9719860 |
| Jilin          |         7826824 |
| Shaanxi        |         4297493 |
| Shandong       |        12114416 |
| Zhejiang       |         5807384 |
| Henan          |         6899010 |
| Hebei          |         6458553 |
| Shanxi         |         4169899 |
| Yunnan         |         2451016 |
| Hunan          |         5439275 |
| Jiangxi        |         3831558 |
| Fujian         |         3575650 |
| Gansu          |         2462631 |
| Guizhou        |         2512087 |
| Anhui          |         5141136 |
| Xinxiang       |         2894705 |
| Guangxi        |         2925142 |
| Inner Mongolia |         4121479 |
| Qinghai        |          700200 |
| Ningxia        |          802362 |
| Hainan         |          557120 |
| Tibet          |          120000 |
+----------------+-----------------+
31 rows in set (0.01 sec)

c. 统计city表中中国人口超过1000万的省

mysql> SELECT district,SUM(population) FROM city WHERE countrycode='CHN' GROUP BY district HAVING SUM(population)>1000000;
+----------------+-----------------+
| district       | SUM(population) |
+----------------+-----------------+
| Shanghai       |         9696300 |
| Peking         |         7569168 |
| Chongqing      |         6351600 |
| Tianjin        |         5286800 |
| Hubei          |         8547585 |
| Heilongjiang   |        11628057 |
| Liaoning       |        15079174 |
| Guangdong      |         9510263 |
| Sichuan        |         7456867 |
| Jiangsu        |         9719860 |
| Jilin          |         7826824 |
| Shaanxi        |         4297493 |
| Shandong       |        12114416 |
| Zhejiang       |         5807384 |
| Henan          |         6899010 |
| Hebei          |         6458553 |
| Shanxi         |         4169899 |
| Yunnan         |         2451016 |
| Hunan          |         5439275 |
| Jiangxi        |         3831558 |
| Fujian         |         3575650 |
| Gansu          |         2462631 |
| Guizhou        |         2512087 |
| Anhui          |         5141136 |
| Xinxiang       |         2894705 |
| Guangxi        |         2925142 |
| Inner Mongolia |         4121479 |
+----------------+-----------------+
27 rows in set (0.00 sec)

d. 统计亚洲各个国家的人口数量

mysql> SELECT country.name,SUM(city.population) FROM city INNER JOIN country ON city.countrycode=country.code WHERE country.continent='asia' GROUP BY country.name;
+----------------------+----------------------+
| name                 | SUM(city.population) |
+----------------------+----------------------+
| Afghanistan          |              2332100 |
| United Arab Emirates |              1728336 |
| Armenia              |              1633100 |
| Azerbaijan           |              2464000 |
| Bangladesh           |              8569906 |
| Bahrain              |               148000 |
| Brunei               |                21484 |
| Bhutan               |                22000 |
| China                |            175953614 |
| Cyprus               |               349400 |
| Georgia              |              1880900 |
| Hong Kong            |              3300633 |
| Indonesia            |             37485695 |
| India                |            123298526 |
| Iran                 |             26032990 |
| Iraq                 |              8926041 |
| Israel               |              2813000 |
| Jordan               |              1847677 |
| Japan                |             77965107 |
| Kazakstan            |              5484200 |
| Kyrgyzstan           |               812100 |
| Cambodia             |               805055 |
| South Korea          |             38999893 |
| Kuwait               |               261252 |
| Laos                 |               628452 |
| Lebanon              |              1340000 |
| Sri Lanka            |              1545000 |
| Macao                |               437500 |
| Maldives             |                71000 |
| Myanmar              |              6203000 |
| Mongolia             |               773700 |
| Malaysia             |              4605141 |
| Nepal                |              1132403 |
| Oman                 |               537096 |
| Pakistan             |             31546745 |
| Philippines          |             30934791 |
| North Korea          |              6476751 |
| Palestine            |               902360 |
| Qatar                |               355000 |
| Saudi Arabia         |             10636700 |
| Singapore            |              4017733 |
| Syria                |              4477784 |
| Thailand             |              7953161 |
| Tajikistan           |               685500 |
| Turkmenistan         |               972600 |
| East Timor           |                47900 |
| Turkey               |             28327028 |
| Taiwan               |             13569336 |
| Uzbekistan           |              5183900 |
| Vietnam              |              9364813 |
| Yemen                |              1743700 |
+----------------------+----------------------+
51 rows in set (0.00 sec)

e. 统计亚洲人口数量前五的国家和省及人口数量

SELECT 
country.name AS `国家`,
city.district AS `省份`,
sum(city.population) AS `人口总数`
FROM city 
INNER JOIN country on city.countrycode=country.code 
WHERE country.Continent='Asia'
GROUP BY country.name,city.district
ORDER BY sum(city.population) DESC
LIMIT 5;