Python-mysql数据库高级查询

Python-mysql数据库高级查询

本节知识点

知识点一: 筛选条件

知识点二: 排序、去重

知识点三: 聚合与分组

知识点四: 限制与分页

Part one :数据准备

执行环境:Ubuntu16.04_server_32bit

运行软件: mysql

执行命令进入mysql命令行:

pyvip@Vip:~$ mysql -uroot -pqwe123
mysql: [Warning] Using a password on the command line interface can be insecure.
Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 64
Server version: 5.7.21-0ubuntu0.16.04.1 (Ubuntu)

Copyright (c) 2000, 2018, Oracle and/or its affiliates. All rights reserved.

Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.

Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

mysql> 

数据准备:

# 学生表
CREATE TABLE students (
  number CHAR(9),   # 学号
  name VARCHAR(20),  # 姓名
  klass VARCHAR(10),    # 班级
  age INT,   # 年龄
  birth DATE   # 生日
);

INSERT INTO students
    VALUES ('201804001', '刘一', 19, 16, '2002-01-01'),
            ('201804002', '陈二', 18, 17, '2001-01-02'),
            ('201804003', '张三', 19, 18, '2000-01-03'),
            ('201804004', '李四', 19, 19, '2001-01-04'),
            ('201804005', '王五', 19, 16, '2002-01-05'),
            ('201804006', '赵六', 18, 19, '1999-01-06'),
            ('201804007', '孙七', 19, 17, '2001-01-07'),
            ('201804008', '周八', 19, 18, '2000-01-08'),
            ('201804009', '吴九', 18, 17, '2001-01-09'),
            ('201804010', '郑十', 19, 18, '2000-01-10');
select * from students;


#结果打印:
+----+-----------+--------+------+------------+
| id | number    | name   | age  | birth      |
+----+-----------+--------+------+------------+
|  1 | 201804001 | 刘一   |   16 | 2002-01-01 |
|  2 | 201804002 | 陈二   |   17 | 2001-01-02 |
|  3 | 201804003 | 张三   |   18 | 2000-01-03 |
|  4 | 201804004 | 李四   |   19 | 2001-01-04 |
|  5 | 201804005 | 王五   |   20 | 2000-01-05 |
|  6 | 201804006 | 赵六   |   21 | 1999-01-06 |
|  7 | 201804007 | 孙七   |   22 | 1999-01-07 |
|  8 | 201804008 | 周八   |   23 | 1999-01-08 |
|  9 | 201804009 | 吴九   |   24 | 1999-01-09 |
| 10 | 201804010 | 郑十   |   25 | 1999-01-10 |
+----+-----------+--------+------+------------+
10 rows in set (0.11 sec)

Part Two :筛选条件

筛选条件 问题引入

问题一: 除了“=”以外,还能有其他的运算符嘛 ?

问题二: 如果有多个条件,该如何做 ?

问题三: 如何查询一个范围中的数据?

问题四: MySQL可以做模糊匹配嘛 ?

运算符
  • 比较运算符
    • 等于: = ( 注意!不是 == )
    • 不等于: != 或 <>
    • 大于: >
    • 大于等于: >=
    • 小于: <
    • 小于等于: <=
    • IS NULL
    • IS NOT NULL
  • 逻辑运算符
    • 与(且): AND
    • 或: OR
    • 非(不是): NOT
NULL 判断:
# 条件筛选
INSERT INTO students VALUES ('201804011', NULL, NULL, NULL, NULL);
mysql> select * from students;
+-----------+--------+-------+------+------------+
| number    | name   | klass | age  | birth      |
+-----------+--------+-------+------+------------+
| 201804001 | 刘一   | 19    |   16 | 2002-01-01 |
| 201804002 | 陈二   | 18    |   17 | 2001-01-02 |
| 201804003 | 张三   | 19    |   18 | 2000-01-03 |
| 201804004 | 李四   | 19    |   19 | 2001-01-04 |
| 201804005 | 王五   | 19    |   16 | 2002-01-05 |
| 201804006 | 赵六   | 18    |   19 | 1999-01-06 |
| 201804007 | 孙七   | 19    |   17 | 2001-01-07 |
| 201804008 | 周八   | 19    |   18 | 2000-01-08 |
| 201804009 | 吴九   | 18    |   17 | 2001-01-09 |
| 201804010 | 郑十   | 19    |   18 | 2000-01-10 |
| 201804011 | NULL   | NULL  | NULL | NULL       |
+-----------+--------+-------+------+------------+
11 rows in set (0.00 sec)
mysql> SELECT * FROM students WHERE name<>'李四';
+-----------+--------+-------+------+------------+
| number    | name   | klass | age  | birth      |
+-----------+--------+-------+------+------------+
| 201804001 | 刘一   | 19    |   16 | 2002-01-01 |
| 201804002 | 陈二   | 18    |   17 | 2001-01-02 |
| 201804003 | 张三   | 19    |   18 | 2000-01-03 |
| 201804005 | 王五   | 19    |   16 | 2002-01-05 |
| 201804006 | 赵六   | 18    |   19 | 1999-01-06 |
| 201804007 | 孙七   | 19    |   17 | 2001-01-07 |
| 201804008 | 周八   | 19    |   18 | 2000-01-08 |
| 201804009 | 吴九   | 18    |   17 | 2001-01-09 |
| 201804010 | 郑十   | 19    |   18 | 2000-01-10 |
+-----------+--------+-------+------+------------+
9 rows in set (0.01 sec)

mysql> SELECT * FROM students WHERE name<>NULL;
Empty set (0.00 sec)

mysql> SELECT * FROM students WHERE name=NULL;
Empty set (0.00 sec)

mysql> SELECT * FROM students WHERE name IS NULL;
+-----------+------+-------+------+-------+
| number    | name | klass | age  | birth |
+-----------+------+-------+------+-------+
| 201804011 | NULL | NULL  | NULL | NULL  |
+-----------+------+-------+------+-------+
1 row in set (0.00 sec)

mysql> SELECT * FROM students WHERE name IS  NOT NULL;
+-----------+--------+-------+------+------------+
| number    | name   | klass | age  | birth      |
+-----------+--------+-------+------+------------+
| 201804001 | 刘一   | 19    |   16 | 2002-01-01 |
| 201804002 | 陈二   | 18    |   17 | 2001-01-02 |
| 201804003 | 张三   | 19    |   18 | 2000-01-03 |
| 201804004 | 李四   | 19    |   19 | 2001-01-04 |
| 201804005 | 王五   | 19    |   16 | 2002-01-05 |
| 201804006 | 赵六   | 18    |   19 | 1999-01-06 |
| 201804007 | 孙七   | 19    |   17 | 2001-01-07 |
| 201804008 | 周八   | 19    |   18 | 2000-01-08 |
| 201804009 | 吴九   | 18    |   17 | 2001-01-09 |
| 201804010 | 郑十   | 19    |   18 | 2000-01-10 |
+-----------+--------+-------+------+------------+
10 rows in set (0.00 sec)
范围查询

连续范围: BETWEEN a AND b

  • a <= value <= b
  • 间隔返回: IN

代码验证:

mysql> mysql> SELECT * FROM students WHERE age BETWEEN 17 AND 18;
+-----------+--------+-------+------+------------+
| number    | name   | klass | age  | birth      |
+-----------+--------+-------+------+------------+
| 201804002 | 陈二   | 18    |   17 | 2001-01-02 |
| 201804003 | 张三   | 19    |   18 | 2000-01-03 |
| 201804007 | 孙七   | 19    |   17 | 2001-01-07 |
| 201804008 | 周八   | 19    |   18 | 2000-01-08 |
| 201804009 | 吴九   | 18    |   17 | 2001-01-09 |
| 201804010 | 郑十   | 19    |   18 | 2000-01-10 |
+-----------+--------+-------+------+------------+
6 rows in set (0.03 sec)

mysql> SELECT * FROM students WHERE age IN (16,19);
+-----------+--------+-------+------+------------+
| number    | name   | klass | age  | birth      |
+-----------+--------+-------+------+------------+
| 201804001 | 刘一   | 19    |   16 | 2002-01-01 |
| 201804004 | 李四   | 19    |   19 | 2001-01-04 |
| 201804005 | 王五   | 19    |   16 | 2002-01-05 |
| 201804006 | 赵六   | 18    |   19 | 1999-01-06 |
+-----------+--------+-------+------+------------+
4 rows in set (0.00 sec)

模糊查询 LIKE(即相似度查询)

常用通配符:

  • 任意多个字符: %
  • 任意一个字符: _

代码验证:

mysql> INSERT INTO students VALUES ('201804012', '李世民', NULL, NULL, NULL);
Query OK, 1 row affected (0.02 sec)

mysql> SELECT * FROM students name LIKE '李%';
ERROR 1064 (42000): You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'LIKE '李%'' at line 1
mysql> SELECT * FROM students WHERE name LIKE '李%';
+-----------+-----------+-------+------+------------+
| number    | name      | klass | age  | birth      |
+-----------+-----------+-------+------+------------+
| 201804004 | 李四      | 19    |   19 | 2001-01-04 |
| 201804012 | 李世民    | NULL  | NULL | NULL       |
+-----------+-----------+-------+------+------------+
2 rows in set (0.00 sec)

mysql> SELECT * FROM students WHERE name LIKE '李_';
+-----------+--------+-------+------+------------+
| number    | name   | klass | age  | birth      |
+-----------+--------+-------+------+------------+
| 201804004 | 李四   | 19    |   19 | 2001-01-04 |
+-----------+--------+-------+------+------------+
1 row in set (0.00 sec)

Part Third :排序与去重

排序 问题引入

问题一: 如果希望查询的结果依据某列排序该怎么做 ?

问题二: 是否支持正序与反序排列 ?

问题三: 如果只查询部分列,能否去重 ?

数据排序

代码样例:

  • SELECT columns FROM tb_name ORDER BY ord_col_1 [asc/desc];

    • 正序: asc(默认)
    • 倒序: desc

    代码验证:

mysql> SELECT * FROM students ORDER BY age;
+-----------+-----------+-------+------+------------+
| number    | name      | klass | age  | birth      |
+-----------+-----------+-------+------+------------+
| 201804011 | NULL      | NULL  | NULL | NULL       |
| 201804012 | 李世民    | NULL  | NULL | NULL       |
| 201804001 | 刘一      | 19    |   16 | 2002-01-01 |
| 201804005 | 王五      | 19    |   16 | 2002-01-05 |
| 201804002 | 陈二      | 18    |   17 | 2001-01-02 |
| 201804007 | 孙七      | 19    |   17 | 2001-01-07 |
| 201804009 | 吴九      | 18    |   17 | 2001-01-09 |
| 201804003 | 张三      | 19    |   18 | 2000-01-03 |
| 201804008 | 周八      | 19    |   18 | 2000-01-08 |
| 201804010 | 郑十      | 19    |   18 | 2000-01-10 |
| 201804004 | 李四      | 19    |   19 | 2001-01-04 |
| 201804006 | 赵六      | 18    |   19 | 1999-01-06 |
+-----------+-----------+-------+------+------------+
12 rows in set (0.01 sec)

mysql> SELECT * FROM students ORDER BY age DESC;
+-----------+-----------+-------+------+------------+
| number    | name      | klass | age  | birth      |
+-----------+-----------+-------+------+------------+
| 201804004 | 李四      | 19    |   19 | 2001-01-04 |
| 201804006 | 赵六      | 18    |   19 | 1999-01-06 |
| 201804003 | 张三      | 19    |   18 | 2000-01-03 |
| 201804008 | 周八      | 19    |   18 | 2000-01-08 |
| 201804010 | 郑十      | 19    |   18 | 2000-01-10 |
| 201804002 | 陈二      | 18    |   17 | 2001-01-02 |
| 201804007 | 孙七      | 19    |   17 | 2001-01-07 |
| 201804009 | 吴九      | 18    |   17 | 2001-01-09 |
| 201804001 | 刘一      | 19    |   16 | 2002-01-01 |
| 201804005 | 王五      | 19    |   16 | 2002-01-05 |
| 201804011 | NULL      | NULL  | NULL | NULL       |
| 201804012 | 李世民    | NULL  | NULL | NULL       |
+-----------+-----------+-------+------+------------+
12 rows in set (0.00 sec)
数据去重

数据重复的定义:两条数据其对应列都相等。

代码样例:

  • SELECT DISTINCT columns FROM tb_name;

  • 通常数据库会设置主键,因此直接查询是不会出现重复的,一般情况下查询非主键的部分列时

    才会使用DISTINCT

mysql> SELECT DISTINCT klass ,age FROM students;
+-------+------+
| klass | age  |
+-------+------+
| 19    |   16 |
| 18    |   17 |
| 19    |   18 |
| 19    |   19 |
| 18    |   19 |
| 19    |   17 |
+-------+------+
6 rows in set (0.00 sec)

mysql> SELECT klass ,age FROM students;
+-------+------+
| klass | age  |
+-------+------+
| 19    |   16 |
| 18    |   17 |
| 19    |   18 |
| 19    |   19 |
| 19    |   16 |
| 18    |   19 |
| 19    |   17 |
| 19    |   18 |
| 18    |   17 |
| 19    |   18 |
+-------+------+
10 rows in set (0.00 sec)

Part Four :聚合与分组

聚合分组 问题引入

问题一: 仅从文字上看,你认为聚合是什么意思 ?

问题二: 聚合通常是为了什么目的 ?

问题三: 分组对于聚合而言意味着什么 ?

问题四: 能否对筛选聚合值 ?

常用聚合函数
  • 统计个数: COUNT(*)
  • 最大值: MAX(column)
  • 最小值: MIN(column)
  • 求和: SUM(column)
  • 平均值: AVG(column)

代码验证:

mysql> SELECT COUNT(*) FROM students;
+----------+
| COUNT(*) |
+----------+
|       10 |
+----------+
1 row in set (0.03 sec)

mysql> SELECT MAX(age) FROM students;
+----------+
| MAX(age) |
+----------+
|       19 |
+----------+
1 row in set (0.02 sec)

mysql> SELECT MIN(age) FROM students;
+----------+
| MIN(age) |
+----------+
|       16 |
+----------+
1 row in set (0.00 sec)

mysql> SELECT SUM(age) FROM students;
+----------+
| SUM(age) |
+----------+
|      175 |
+----------+
1 row in set (0.00 sec)

mysql> SELECT AVG(age) FROM students;
+----------+
| AVG(age) |
+----------+
|  17.5000 |
+----------+
1 row in set (0.00 sec)
分组查询

代码样例:

SELECT group_column, aggregations FROM tb_name GROUP group_column;

注:在分组的情况下,只应该出现分组列和聚合列其他的列没有意义 !

代码验证:

mysql> SELECT klass ,AVG(age) FROM students GROUP BY klass;
+-------+----------+
| klass | AVG(age) |
+-------+----------+
| 18    |  17.6667 |
| 19    |  17.4286 |
+-------+----------+
2 rows in set (0.01 sec)

以上语句即表示:以klass为分组查询各个分组的平均值

聚合筛选

代码样例:

SELECT group_column, aggregations FROM tb_name GROUP group_column HAVING conditions;

关于筛选关键字的总结:

假如说,一个查询中同时包含了ON、WHERE、HAVING那么它们的执行顺序是:

  • 先是筛选: ON
  • 然后筛选: WHERE
  • 最后筛选: HAVING

代码验证:

mysql> SELECT klass, COUNT(*) FROM students GROUP BY klass HAVING COUNT(*)>4;
+-------+----------+
| klass | COUNT(*) |
+-------+----------+
| 19    |        7 |
+-------+----------+
1 row in set (0.01 sec)

mysql> SELECT klass, COUNT(*) FROM students GROUP BY klass WHERE COUNT(*)>4;
ERROR 1064 (42000): You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'WHERE COUNT(*)>4' at line 1

关于ONWHERE关键字的筛选次序在Python-mysql数据库基础补充的连接查询中有叙述由此我在做一下总结:

eg:

SELECT subject_number, grade
    FROM ( students JOIN grades ON students.number=grades.student_number )
    WHERE name='张三';

有这条语句可以得出:关于ONWHERE关键字的筛选次序是先是筛选: ON 然后筛选: WHERE,再根据上一条代码验证可以得出:三条关键字在运行过程中的先后次序为ON>WHERE>HANING

Part Five :限制与分页

排序与分页 问题引入

问题一: 如果一次性不需要那么多数据,该如何做 ?

问题二: 能否从指定位置开始取 ?

问题三: 分页是如何做的 ?

限制输出结果个数

代码样例:

  • SELECT columns FROM tb_name LIMIT count
  • SELECT columns FROM tb_name LIMIT start, count

代码验证:

mysql> SELECT * FROM students;
+-----------+--------+-------+------+------------+
| number    | name   | klass | age  | birth      |
+-----------+--------+-------+------+------------+
| 201804001 | 刘一   | 19    |   16 | 2002-01-01 |
| 201804002 | 陈二   | 18    |   17 | 2001-01-02 |
| 201804003 | 张三   | 19    |   18 | 2000-01-03 |
| 201804004 | 李四   | 19    |   19 | 2001-01-04 |
| 201804005 | 王五   | 19    |   16 | 2002-01-05 |
| 201804006 | 赵六   | 18    |   19 | 1999-01-06 |
| 201804007 | 孙七   | 19    |   17 | 2001-01-07 |
| 201804008 | 周八   | 19    |   18 | 2000-01-08 |
| 201804009 | 吴九   | 18    |   17 | 2001-01-09 |
| 201804010 | 郑十   | 19    |   18 | 2000-01-10 |
+-----------+--------+-------+------+------------+
10 rows in set (0.00 sec)

mysql> SELECT * FROM students LIMIT 3;
+-----------+--------+-------+------+------------+
| number    | name   | klass | age  | birth      |
+-----------+--------+-------+------+------------+
| 201804001 | 刘一   | 19    |   16 | 2002-01-01 |
| 201804002 | 陈二   | 18    |   17 | 2001-01-02 |
| 201804003 | 张三   | 19    |   18 | 2000-01-03 |
+-----------+--------+-------+------+------------+
3 rows in set (0.01 sec)

mysql> SELECT * FROM students LIMIT 3,3;
+-----------+--------+-------+------+------------+
| number    | name   | klass | age  | birth      |
+-----------+--------+-------+------+------------+
| 201804004 | 李四   | 19    |   19 | 2001-01-04 |
| 201804005 | 王五   | 19    |   16 | 2002-01-05 |
| 201804006 | 赵六   | 18    |   19 | 1999-01-06 |
+-----------+--------+-------+------+------------+
3 rows in set (0.01 sec)
数据分页

代码样例:

SELECT columns FROM tb_name LIMIT (n-1)*m, m

在python里面定义俩变量:

  • n 表示第几页
  • m 每页多少个

代码验证:

代码编辑器:pycharm2016

运行环境:Ubuntu16.04_server_32bit(python3)

任务:用Python实现分页查询

(pycharm远程连接Ubuntu16.04_server_32bit虚拟环境下代码实现

也可以直接在Ubuntu16.04_server_32bit运行)

import pymysql
db_config = {
    'host': '127.0.0.1',
    'user': 'root',
    'password': 'qwe123',
    'db': 'python3',
    'charset': 'utf8',
}
def sql_check(n,m):
    cur = conn.cursor()
    sql = 'SELECT * FROM student LIMIT %s,%s' %((n-1)*m,m)
    sql2 = 'SELECT * FROM student'
    rv = cur.execute(sql)
    res = cur.fetchall()
    for entry in res:
        print(entry)
    cur.close()
conn = pymysql.connect(**db_config)
try:
    while True :
        n = input('请输入查询的页数:')
        if n == 'q':
            break
        if n.isdigit():
            sql_check(int(n),3)
        else:
            print("输入的不是数字!!!!")
except Exception as e :
    print('执行过程中发生了异常',e)
    conn.rollback()
finally:
    conn.commit()
    conn.close()

结果打印:

ssh://pyvip@192.168.206.128:22/home/pyvip/.virtualenvs/py3env/bin/python -u /home/pyvip/py_case/mysql_wege.py
请输入查询的页数:1
1
('201804001', '刘一', 16, datetime.date(2002, 1, 1))
('201804002', '陈二', 17, datetime.date(2001, 1, 2))
('201804003', '张三', 18, datetime.date(2000, 1, 3))
请输入查询的页数:2
2
('201804004', '李四', 19, datetime.date(2001, 1, 4))
('201804005', '王五', 20, datetime.date(2000, 1, 5))
('201804006', '赵六', 21, datetime.date(1999, 1, 6))
请输入查询的页数:3
3
('201804007', '孙七', 22, datetime.date(1999, 1, 7))
('201804008', '周八', 23, datetime.date(1999, 1, 8))
('201804009', '吴九', 24, datetime.date(1999, 1, 9))
请输入查询的页数:4
4
('201804010', '郑十', 25, datetime.date(1999, 1, 10))
请输入查询的页数:q
q

进程已结束,退出代码0

你可能感兴趣的:(python,基础知识,数据库基础)