表(修改、排序、分页、表关联)

where子句(条件查询):按照条件表达式指定的条件进行查询。

group by子句(分组):按照属性名指定的字段进行分组。group by子句通常和count()sum()等聚合函数一起使用。

having子句(筛选):有group by才能having子句,只有满足条件表达式中指定的条件的才能够输出。

order by子句(排序):按照属性名指定的字段进行排序。排序方式由“asc”“desc”两个参数指出,默认是按照“asc”来排序,即升序。

limit(限制结果集)。

 

 

 

 

mysql中五种常用的聚合函数:

1max(列名):求最大值。

2min(列名):求最小值。

2sum(列名):求和。

4avg(列名):求平均值。

5count(列名):统计记录的条数。

 

 

为了方便查看数据,可以对数据进行排序

语法:order by 字段 asc 或者 desc

说明   按照某字段正序,倒序使用desc

将行数据按照列1进行排序,如果某些行列1的值相同时,则按照列2排序,以此类推

默认按照列值从小到大排列(asc

asc从小到大排列,即升序

desc从大到小排序,即降序

1:查询学生信息,按学号降序

select * from student order by id desc  

2:查询学生信息,按名称升序

select * from student order by name asc

3:显示所有的学生信息,先按照年龄从大-->小排序,当年龄相同时 按照身高从高-->矮排序

select * from student order by age desc,height desc

 

 

聚合函数

 

 

 

1count函数

 

count(*):返回表中满足where条件的行的数量

 

mysql> select count(*) from salary_tab where salary='1000';

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

| count(*) |

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

|        2 |

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

 

mysql> select count(*) from salary_tab;  #没有条件,默认统计表数据行数

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

| count(*) |

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

|        5 |

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

count():返回列值非空的行的数量

 

mysql> select count(salary) from salary_tab;

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

| count(salary) |

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

|             4 |

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

count(distinct ):返回列值非空的、并且列值不重复的行的数量

 

mysql> select count(distinct salary) from salary_tab;

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

| count(distinct salary) |

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

|                      3 |

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

count(expr):根据表达式统计数据

 

mysql> select * from TT;

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

| UNIT | DATE       |

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

| a    | 2018-04-03 |

| a    | 2017-12-12 |

| b    | 2018-01-01 |

| b    | 2018-04-03 |

| c    | 2016-06-06 |

| d    | 2018-03-03 |

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

6 rows in set (0.00 sec)

 

mysql> select UNIT as '单位',

    ->     COUNT(TO_DAYS(DATE)=TO_DAYS(NOW()) or null) as '今日统计',

    ->     COUNT(YEAR(DATE)=YEAR(NOW()) or null) as '今年统计'

    -> from v_jjd

    -> group by JJDW;

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

| 单位  | 今日统计  | 今年统计  |

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

| a    |        1 |        1 |

| b    |        1 |        2 |

| c    |        0 |        0 |

| d    |        0 |        1 |

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

4 rows in set (0.00 sec)

 

 

2maxmin函数---统计列中的最大最小值

 

mysql> select max(salary) from salary_tab;

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

| max(salary) |

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

|     3000.00 |

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

 

mysql> select min(salary) from salary_tab;

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

| min(salary) |

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

|     1000.00 |

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

注意:如果统计的列中只有NULL值,那么MAXMIN就返回NULL

 

 

 

3sumavg函数---求和与求平均

 

!!表中列值为null的行不参与计算

 

mysql> select sum(salary) from salary_tab;

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

| sum(salary) |

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

|     7000.00 |

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

 

mysql> select avg(salary) from salary_tab;

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

| avg(salary) |

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

| 1750.000000 |

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

 

mysql> select avg(ifnull(salary,0)) from salary_tab;

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

| avg(ifnull(salary,0)) |

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

|           1400.000000 |

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

注意:要想列值为NULL的行也参与组函数的计算,必须使用IFNULL函数对NULL值做转换。

 

 

 

 

 

二、分组SELECT

 

SELECT select_expr [, select_expr ...]

 

    [FROM table_references

 

      [PARTITION partition_list]

 

    [WHERE where_condition]

 

    [GROUP BY {col_name | expr | position}

 

      [ASC | DESC], ... [WITH ROLLUP]]

 

    [HAVING where_condition]

 

    [ORDER BY {col_name | expr | position}

 

      [ASC | DESC], ...]

 

[LIMIT {[offset,] row_count | row_count OFFSET offset}]

分组SELECT的基本格式:

 

  select [聚合函数] 字段名 from 表名

 

    [where 查询条件]

 

    [group by 字段名]

 

    [having 过滤条件]

 

1group by子句

 

  根据给定列或者表达式的每一个不同的值将表中的行分成不同的组,使用组函数返回每一组的统计信息

 

规则:

 

  ①出现在SELECT子句中的单独的列,必须出现在GROUP BY子句中作为分组列

 

  ②分组列可以不出现在SELECT子句中

 

  ③分组列可出现在SELECT子句中的一个复合表达式中

 

  ④如果GROUP BY后面是一个复合表达式,那么在SELECT子句中,它必须整体作为一个表达式的一部分才能使用。

 

1)指定一个列进行分组

 

mysql> select salary,count(*) from salary_tab

    -> where salary>=2000

    -> group by salary;   

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

| salary  | count(*) |

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

| 2000.00 |        1 |

| 3000.00 |        1 |

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

2)指定多个分组列,‘大组中再分小组’

 

mysql> select userid,count(salary) from salary_tab

    -> where salary>=2000

    -> group by salary,userid;   

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

| userid | count(salary) |

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

|      2 |             1 |

|      3 |             1 |

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

3)根据表达式分组

 

mysql> select year(payment_date),count(*)

    -> from PENALTIES

    -> group by year(payment_date);

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

| year(payment_date) | count(*) |

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

|               1980 |        3 |

|               1981 |        1 |

|               1982 |        1 |

|               1983 |        1 |

|               1984 |        2 |

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

5 rows in set (0.00 sec)

4)带有排序的分组:如果分组列和排序列相同,则可以合并group byorder by子句

 

mysql> select teamno,count(*)

    -> from MATCHES

    -> group by teamno

    -> order by teamno desc;

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

| teamno | count(*) |

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

|      2 |        5 |

|      1 |        8 |

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

2 rows in set (0.00 sec)

 

mysql> select teamno,count(*)

    -> from MATCHES

    -> group by teamno desc;  #可以把desc(或者asc)包含到group by子句中简化

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

| teamno | count(*) |

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

|      2 |        5 |

|      1 |        8 |

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

2 rows in set (0.00 sec)

对于分组聚合注意:

 

  通过select在返回集字段中,这些字段要么就要包含在group by语句后面,作为分组的依据,要么就要被包含在聚合函数中。我们可以将group by操作想象成如下的一个过程:首先系统根据select语句得到一个结果集,然后根据分组字段,将具有相同分组字段的记录归并成了一条记录。这个时候剩下的那些不存在与group by语句后面作为分组依据的字段就很有可能出现多个值,但是目前一种分组情况只有一条记录,一个数据格是无法放入多个数值的,所以这个时候就需要通过一定的处理将这些多值的列转化成单值,然后将其放在对应的数据格中,那么完成这个步骤的就是前面讲到的聚合函数,这也就是为什么这些函数叫聚合函数了。

 

 

 

2GROUP_CONCAT()函数

 

  函数的值等于属于一个组的指定列的所有值,以逗号隔开,并且以字符串表示。

 

1:对于每个球队,得到其编号和所有球员的编号

 

mysql> select teamno,group_concat(playerno)

    -> from MATCHES

    -> group by teamno;

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

| teamno | group_concat(playerno) |

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

|      1 | 6,6,6,44,83,2,57,8     |

|      2 | 27,104,112,112,8       |

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

2 rows in set (0.01 sec)

如果没有group by子句,group_concat返回一列的所有值

 

2:得到所有的罚款编号列表

 

mysql> select group_concat(paymentno)

    -> from PENALTIES;

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

| group_concat(paymentno) |

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

| 1,2,3,4,5,6,7,8         |

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

1 row in set (0.00 sec)

 

 

3with rollup子句:用来要求在一条group by子句中进行多个不同的分组

 

用的比较少点,但是有时可以根据具体的需求使用

 

  如果有子句GROUP BY E1,E2,E3,E4 WITH ROLLUP

 

  那么将分别执行以下分组:[E1,E2,E3,E4][E1,E2,E3][E1,E2][E1][]

 

注意:[ ]表示所有行都分在一组中

 

示例:按照球员的性别和居住城市,统计球员的总数;统计每个性别球员的总数;统计所有球员的总数

 

mysql> select sex,town,count(*)

    -> from PLAYERS

    -> group by sex,town with rollup;

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

| sex | town      | count(*) |

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

| F   | Eltham    |        2 |

| F   | Inglewood |        1 |

| F   | Midhurst  |        1 |

| F   | Plymouth  |        1 |

| F   | NULL      |        5 |

| M   | Douglas   |        1 |

| M   | Inglewood |        1 |

| M   | Stratford |        7 |

| M   | NULL      |        9 |

| NULL | NULL      |       14 |

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

10 rows in set (0.00 sec)

 

 

4HAVING子句:对分组结果进行过滤

 

注意:

 

  不能使用WHERE子句对分组后的结果进行过滤

 

  不能在WHERE子句中使用组函数,仅用于过滤行

 

mysql> select playerno

    -> from PENALTIES

    -> where count(*)>1

    -> group by playerno;

ERROR 1111 (HY000): Invalid use of group function

因为WHERE子句比GROUP BY先执行,而组函数必须在分完组之后才执行,且分完组后必须使用having子句进行结果集的过滤。

 

基本语法:

 

SELECT   select_expr [, select_expr ...]

 

   FROM  table_name

 

   [WHERE where_condition]

 

   [GROUP BY {col_name | expr} [ASC | DESC], ... [WITH ROLLUP]]

 

[HAVING where_condition]

!!!having子语句与where子语句区别:

 

  where子句在分组前对记录进行过滤;

 

  having子句在分组后对记录进行过滤

 

mysql> select salary,count(*) from salary_tab

    -> where salary>=2000

    -> group by salary

    -> having count(*)>=0;

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

| salary  | count(*) |

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

| 2000.00 |        1 |

| 3000.00 |        1 |

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

1HAVING可以单独使用而不和GROUP BY配合,如果只有HAVING子句而没有GROUP BY,表中所有的行分为一组

 

2HAVING子句中可以使用组函数

 

3HAVING子句中的列,要么出现在一个组函数中,要么出现在GROUP BY子句中(否则出错)

 

mysql> select town,count(*)

    -> from PLAYERS

    -> group by town

    -> having birth_date>'1970-01-01';

ERROR 1054 (42S22): Unknown column 'birth_date' in 'having clause'

mysql> select town,count(*)

    -> from PLAYERS

    -> group by town

    -> having town in ('Eltham','Midhurst');

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

| town     | count(*) |

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

| Eltham   |        2 |

| Midhurst |        1 |

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

2 rows in set (0.00 sec)

 

 

limit 分段取值

 

语法 limi m,n

 

m为其实位置,n为取几个

 

select * from student limit 0,2

 

从第一个开始取,取两个,如果不写第一个参数,就是默认从第一个参数取值,取n个

 

select * from student limit 2

 

 

连接查询(join 语法)

 

join 用于多表中字段之间的联系,语法如下:

... FROM table1 INNER|LEFT|RIGHT JOIN table2 ON conditiona

table1:左表;table2:右表。

JOIN 按照功能大致分为如下三类:

INNER JOIN(内连接,或等值连接):取得两个表中存在连接匹配关系的记录。

LEFT JOIN(左连接):取得左表(table1)完全记录,即是右表(table2)并无对应匹配记录。

RIGHT JOIN(右连接):与 LEFT JOIN 相反,取得右表(table2)完全记录,即是左表(table1)并无匹配对应记录。

注意:mysql不支持Full join,不过可以通过UNION 关键字来合并 LEFT JOIN RIGHT JOIN来模拟FULL join.

接下来给出一个列子用于解释下面几种分类。如下两个表(A,B)

  1. mysql> select A.id,A.name,B.name from A,B where A.id=B.id;
  2. +----+-----------+-------------+
  3. | id | name       | name             |
  4. +----+-----------+-------------+
  5. |  1 | Pirate       | Rutabaga      |
  6. |  2 | Monkey    | Pirate            |
  7. |  3 | Ninja         | Darth Vader |
  8. |  4 | Spaghetti  | Ninja             |
  9. +----+-----------+-------------+
  10. 4 rows in set (0.00 sec)

.Inner join

内连接,也叫等值连接,inner join产生同时符合AB的一组数据。

  1. mysql> select * from A inner join B on A.name = B.name;
  2. +----+--------+----+--------+
  3. | id | name   | id | name   |
  4. +----+--------+----+--------+
  5. |  1 | Pirate |  2 | Pirate |
  6. |  3 | Ninja  |  4 | Ninja  |
  7. +----+--------+----+--------+

 

.Left join

  1. mysql> select * from A left join B on A.name = B.name;
  2. #或者:select * from A left outer join B on A.name = B.name;
  3. +----+-----------+------+--------+
  4. | id | name      | id   | name   |
  5. +----+-----------+------+--------+
  6. |  1 | Pirate    |    2 | Pirate |
  7. |  2 | Monkey    | NULL | NULL   |
  8. |  3 | Ninja     |    4 | Ninja  |
  9. |  4 | Spaghetti | NULL | NULL   |
  10. +----+-----------+------+--------+
  11. 4 rows in set (0.00 sec)

left join,(或left outer join:Mysql中两者等价,推荐使用left join.)左连接从左表(A)产生一套完整的记录,与匹配的记录(右表(B)) .如果没有匹配,右侧将包含null

 

如果想只从左表(A)中产生一套记录,但不包含右表(B)的记录,可以通过设置where语句来执行,如下:

  1. mysql> select * from A left join B on A.name=B.name where A.id is null or B.id is null;
  2. +----+-----------+------+------+
  3. | id | name      | id   | name |
  4. +----+-----------+------+------+
  5. |  2 | Monkey    | NULL | NULL |
  6. |  4 | Spaghetti | NULL | NULL |
  7. +----+-----------+------+------+
  8. 2 rows in set (0.00 sec)

 

同理,还可以模拟inner join. 如下:

  1. mysql> select * from A left join B on A.name=B.name where A.id is not null and B.id is not null;
  2. +----+--------+------+--------+
  3. | id | name   | id   | name   |
  4. +----+--------+------+--------+
  5. |  1 | Pirate |    2 | Pirate |
  6. |  3 | Ninja  |    4 | Ninja  |
  7. +----+--------+------+--------+
  8. 2 rows in set (0.00 sec)

求差集:

根据上面的例子可以求差集,如下:

  1. SELECT * FROM A LEFT JOIN B ON A.name = B.name
  2. WHERE B.id IS NULL
  3. union
  4. SELECT * FROM A right JOIN B ON A.name = B.name
  5. WHERE A.id IS NULL;
  6. # 结果
  7. +------+-----------+------+-------------+
  8. | id   | name      | id   | name        |
  9. +------+-----------+------+-------------+
  10. |    2 | Monkey    | NULL | NULL        |
  11. |    4 | Spaghetti | NULL | NULL        |
  12. | NULL | NULL      |    1 | Rutabaga    |
  13. | NULL | NULL      |    3 | Darth Vader |
  14. +------+-----------+------+-------------+

 

.Right join

  1. mysql> select * from A right join B on A.name = B.name;
  2. +------+--------+----+-------------+
  3. | id   | name   | id | name        |
  4. +------+--------+----+-------------+
  5. | NULL | NULL   |  1 | Rutabaga    |
  6. |    1 | Pirate |  2 | Pirate      |
  7. | NULL | NULL   |  3 | Darth Vader |
  8. |    3 | Ninja  |  4 | Ninja       |
  9. +------+--------+----+-------------+
  10. 4 rows in set (0.00 sec)

left join

 

 

Mysql建表思路理解

 

一对一   one on one

 

一张表的一条记录一定只能与另外一张表的一条记录进行对应,反之亦然。  学生表:姓名,性别,年龄,身高,体重,籍贯,家庭住址,紧急联系人 其中姓名、性别、年龄、身高,体重属于常用数据,但是籍贯、住址和联系人为不常用数据 如果每次查询都是查询所有数据,不常用的数据就会影响效率,实际又不用 常用信息表:ID(P),姓名,性别,年龄,身高,体重 不常用信息表:ID(P),籍贯,家庭住址,紧急联系人  解决方案:将常用的和不常用的信息分享存储,分成两张表 不常用信息表和常用信息表,保证不常用信息表与常用信息表能够对应上:找一个具有唯一性的 字段来共同连接两张表。 一个常用表中的一条记录永远只能在一张不常用表中匹配一条记录,反之亦然。

 

 

 

一对多  one on many

 

 

一张表中有一条记录可以对应另外一张表中的多条记录;但是反过来,另外一张表的一条记录 只能对应第一张表的一条记录,这种关系就是一对多或多对一 母亲与孩子的关系:母亲,孩子两个实体 母亲表:ID(P),名字,年龄,性别 孩子表:ID(P),名字,年龄,性别 以上关系:一个妈妈可以在孩子表中找到多条记录(也可能是一条),但是一个孩子只能找到一个妈妈 是一种典型的一对多的关系。 但是以上设计:解决了实体的设计表问题,但是没有解决关系问题,孩子找不到母亲,母亲也找不到孩子  解决方案:在某一张表中增加一个字段,能够找到另外一张表中的记录:在孩子表中增加一个字段 指向母亲表,因为孩子表的记录只能匹配到一条母亲表的记录。 母亲表:ID(P),名字,年龄,性别 孩子表:ID(P),名字,年龄,性别,母亲表ID(母亲表主键)

 

 

 

 

 

 

多对多 many on many

 

一对表中(A)的一条记录能够对应另外一张表(B)中的多条记录;同时B表中的一条记录 也能对应A表中的多条记录  老师和学生 老师表 T_ID(P),姓名,性别 学生表 S_ID(P),姓名,性别 以上设计方案:实现了实体的设计,但是没有维护实体的关系 一个老师教过多个学生,一个学生也被多个老师教过  解决方案:增加一张中间关系表 老师与学生的关系表:ID(P),T_ID,S_ID  老师表与中间表形成一对多的关系,而中间表是多表;维护了能够唯一找到一表的关系; 同样的学生表与中间表也是一个一对多的关系;  学生找老师:找出学生ID--->中间表寻找匹配记录(多条)--->老师表匹配(一条) 老师找学生:找出老师ID--->中间表寻找匹配记录(多条)--->学生表匹配(一条)

转载于:https://www.cnblogs.com/jiangyijiangPython/p/10003770.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值