昨天在说MySQL的分组(group by)时,最后有提到为什么会多出来一行--> null, 原来null表示所有人加起来的数。
mysql> select name,sum(scores) as scores_count from teacher group by name with rollup;
+--------+--------------+
| name | scores_count |
+--------+--------------+
| 张三 | 158 |
| 李四 | 88 |
| 柳九 | 100 |
| 王五 | 94 |
| 胡八 | 92 |
| 赵六 | 49 |
| NULL | 581 |
+--------+--------------+
7 rows in set (0.00 sec)
这个null看起来很难受,能不能显示为 总计、总量什么的呢?
答案是可以的。但是需要用到coalesce语法。语法为:
select coalesce(a,b,c);
如果a == null, 则选择b; 如果b==null,则选择c;如果a!=null,则选择a;如果a b c 都为null ,则返回为null。那么当name != null的时候,就显示用户的名字,如果名字为null时,就显示为 总数。其实和java里的循环很像。
我们来看看实例:
mysql> select coalesce(name,"总数"),sum(scores) from teacher group by name with rollup;
+-------------------------+-------------+
| coalesce(name,"总数") | sum(scores) |
+-------------------------+-------------+
| 张三 | 158 |
| 李四 | 88 |
| 柳九 | 100 |
| 王五 | 94 |
| 胡八 | 92 |
| 赵六 | 49 |
| 总数 | 581 |
+-------------------------+-------------+
7 rows in set (0.03 sec)
OK 好了!
接下来,说下MySQL中join的使用。这可是MySQL中的一个大重点!
先说下用法: 可以从多个数据库表中读取数据;
使用join在两个或多个数据库表中查询数据;
可以在 SELECT, UPDATE 和 DELETE 语句中使用 Mysql 的 JOIN 来联合多表查询。
join按照功能大致分为三大类:
inner join 内连接或等值连接: 获取两个表中字段匹配关系的记录 可以忽略inner 直接写 join
left join 左连接: 获取左表所有记录,即使右表没有对应匹配的记录
right join 右连接: 获取右表所有记录,即使左表没有对应匹配的记录
先看内连接 inner join
直接上实例:
mysql> select * from teacher;
+----+--------+------------+--------+
| id | name | time | scores |
+----+--------+------------+--------+
| 1 | 张三 | 2020-06-28 | 77 |
| 2 | 李四 | 2020-06-28 | 88 |
| 3 | 王五 | 2020-06-28 | 66 |
| 4 | 赵六 | 2020-06-28 | 49 |
| 5 | 张三 | 2020-06-29 | 81 |
| 6 | 胡八 | 2020-06-29 | 92 |
| 7 | 柳九 | 2020-06-29 | 100 |
| 8 | 王五 | 2020-06-29 | 28 |
+----+--------+------------+--------+
8 rows in set (0.01 sec)
mysql> select * from course;
+----+----------+
| id | name |
+----+----------+
| 1 | 张三 |
| 2 | lucy |
| 3 | jack |
| 4 | Tom |
| 5 | Shanshan |
| 6 | Liulang |
| 7 | 胡扯 |
| 8 | 张三 |
| 9 | 李四 |
+----+----------+
9 rows in set (0.00 sec)
我们通过和teacher、course有联系的name字段来获取对应的scores值
mysql> select a.id,a.name,a.time,a.scores,b.id,b.name from teacher a inner join course b on a.name = b.name;
+----+--------+------------+--------+----+--------+
| id | name | time | scores | id | name |
+----+--------+------------+--------+----+--------+
| 1 | 张三 | 2020-06-28 | 77 | 1 | 张三 |
| 5 | 张三 | 2020-06-29 | 81 | 1 | 张三 |
| 1 | 张三 | 2020-06-28 | 77 | 8 | 张三 |
| 5 | 张三 | 2020-06-29 | 81 | 8 | 张三 |
| 2 | 李四 | 2020-06-28 | 88 | 9 | 李四 |
+----+--------+------------+--------+----+--------+
5 rows in set (0.00 sec)
我们可以看到对应的语法为:
select 你想显示的表名(多个表的都可以)对应的列名 from 数据库表a inner join 数据库表b on 两个数据库表之间的联系
inner join是交集,两个表中都有的东西,如下图
我们试试把inner去掉,只要 join看看是不是结果也一样
mysql> select a.id,a.name,a.time,a.scores,b.id,b.name from teacher a join course b on a.name = b.name;
+----+--------+------------+--------+----+--------+
| id | name | time | scores | id | name |
+----+--------+------------+--------+----+--------+
| 1 | 张三 | 2020-06-28 | 77 | 1 | 张三 |
| 5 | 张三 | 2020-06-29 | 81 | 1 | 张三 |
| 1 | 张三 | 2020-06-28 | 77 | 8 | 张三 |
| 5 | 张三 | 2020-06-29 | 81 | 8 | 张三 |
| 2 | 李四 | 2020-06-28 | 88 | 9 | 李四 |
+----+--------+------------+--------+----+--------+
5 rows in set (0.00 sec)
没错,结果是一样的
然后我们对结果再进行下优化,显示的数据有些重复,比如最后的id和name就显示重复了,没必要
mysql> select a.id,a.name,a.time,a.scores from teacher a join course b on a.name = b.name;
+----+--------+------------+--------+
| id | name | time | scores |
+----+--------+------------+--------+
| 1 | 张三 | 2020-06-28 | 77 |
| 5 | 张三 | 2020-06-29 | 81 |
| 1 | 张三 | 2020-06-28 | 77 |
| 5 | 张三 | 2020-06-29 | 81 |
| 2 | 李四 | 2020-06-28 | 88 |
+----+--------+------------+--------+
5 rows in set (0.00 sec)
我们可以把数据库表b要显示的数据都删除掉,这样显示就好了很多
然后再核查下,数据显示的是否正确
teacher表和course表的name字段中,相同的有: 张三、李四
其中teacher表中,有2个张三,course表中有2个张三,结果表中有四个张三
teacher表中有1个李四,course表中没有李四,结果表中有1个李四
正确!
我们再来试试如果两个表中的字段不匹配,没有对应的值,会有什么结果
实例如下:
mysql> select a.id,a.name,a.time,a.scores from teacher a join course b on a.name = b.id;
Empty set (0.00 sec)
看吧,果然是空的~~哈哈
下面我们来看下 left join
left join 与 join 有所不同。MySQL LEFT JOIN 会读取左边数据表的全部数据,即便右边表无对应数据。
上面返回为空的例子拿到这里就很好,大家可以看下
mysql> select a.id,a.name,a.time,a.scores from teacher a left join course b on a.name = b.id;
+----+--------+------------+--------+
| id | name | time | scores |
+----+--------+------------+--------+
| 1 | 张三 | 2020-06-28 | 77 |
| 2 | 李四 | 2020-06-28 | 88 |
| 3 | 王五 | 2020-06-28 | 66 |
| 4 | 赵六 | 2020-06-28 | 49 |
| 5 | 张三 | 2020-06-29 | 81 |
| 6 | 胡八 | 2020-06-29 | 92 |
| 7 | 柳九 | 2020-06-29 | 100 |
| 8 | 王五 | 2020-06-29 | 28 |
+----+--------+------------+--------+
8 rows in set (0.01 sec)
这是teacher表中所有的数据吗?
mysql> select * from teacher;
+----+--------+------------+--------+
| id | name | time | scores |
+----+--------+------------+--------+
| 1 | 张三 | 2020-06-28 | 77 |
| 2 | 李四 | 2020-06-28 | 88 |
| 3 | 王五 | 2020-06-28 | 66 |
| 4 | 赵六 | 2020-06-28 | 49 |
| 5 | 张三 | 2020-06-29 | 81 |
| 6 | 胡八 | 2020-06-29 | 92 |
| 7 | 柳九 | 2020-06-29 | 100 |
| 8 | 王五 | 2020-06-29 | 28 |
+----+--------+------------+--------+
8 rows in set (0.00 sec)
嗯,没错,是的
如果两个数据库表的列有对应关系,会怎么样呢?
mysql> select a.id,a.name,a.time,a.scores from teacher a left join course b on a.name = b.name;
+----+--------+------------+--------+
| id | name | time | scores |
+----+--------+------------+--------+
| 1 | 张三 | 2020-06-28 | 77 |
| 5 | 张三 | 2020-06-29 | 81 |
| 1 | 张三 | 2020-06-28 | 77 |
| 5 | 张三 | 2020-06-29 | 81 |
| 2 | 李四 | 2020-06-28 | 88 |
| 3 | 王五 | 2020-06-28 | 66 |
| 4 | 赵六 | 2020-06-28 | 49 |
| 6 | 胡八 | 2020-06-29 | 92 |
| 7 | 柳九 | 2020-06-29 | 100 |
| 8 | 王五 | 2020-06-29 | 28 |
+----+--------+------------+--------+
10 rows in set (0.00 sec)
就是把左边表中的数据和右边表中也符合a.name = b.name的数据加到了一起
同样,right join 也是一样,会读取右边数据表的全部数据,即便左边边表无对应数据。
mysql> select a.id,b.name,a.scores from teacher a right join course b on a.name = b.name;
+------+----------+--------+
| id | name | scores |
+------+----------+--------+
| 1 | 张三 | 77 |
| 1 | 张三 | 77 |
| 2 | 李四 | 88 |
| 5 | 张三 | 81 |
| 5 | 张三 | 81 |
| NULL | lucy | NULL |
| NULL | jack | NULL |
| NULL | Tom | NULL |
| NULL | Shanshan | NULL |
| NULL | Liulang | NULL |
| NULL | 胡扯 | NULL |
+------+----------+--------+
11 rows in set (0.01 sec)
结果表就是 inner join结果+ 右表除了inner部分的数据,然后没有的数据补齐null
好的,今天就到这里