查看源文件

MySQL入门

数据库概念

  1. 关系型数据库:MySQL、Oracle、SQL server等

    • 采用二维表格存储数据。数据和数据之间,和字段之间有关联,数据高度一致。

    • 事务通常强调 ACID 特性:原子性(Atomicity)、一致性(Consistency)、隔离性(Isolation)和持久性(Durability)。

      (事务、以及ACID特性的详细解释待补充)

    • 优点:易于理解,使用方便,易于维护。

    • 限制:海量数据和高并发场景通常需要结合索引、分区、缓存与硬件资源优化。

  2. 非关系型数据库:Redis、MongoDB等

    • 数据存储格式可以是键值对、文档、图片等,结构不固定。

    • 优点:可按场景选择键值、文档等数据模型;读写性能和扩展性取决于具体产品与负载。

    • 限制:查询语言和事务能力取决于具体产品,不能一概而论。

  3. 数据库构成

    • 表:字段 (列)、记录(行)
    • 主键:primary key,唯一标识每条记录,可定义一列或多列,不能有重复或空值

操作数据库和数据表

  1. 创建数据库

    CREATE DATABASE test_db;
  2. 选定某个数据库

    USE test_db;  -- 选定数据库后再操作数据表
  3. 创建数据表

    mysql> CREATE TABLE FRUITS(  # 注意每句之后的逗号和最后的分号
        -> f_id char(10) NOT NULL,
        -> s_id INT NOT NULL,
        -> f_name char(255) NOT NULL,
        -> f_price decimal(8,2) NOT NULL,
        -> PRIMARY KEY(f_id)
        -> );
  4. 插入数据

    mysql> INSERT INTO fruits (f_id, s_id, f_name, f_price)
        -> VALUES ('a1', 101, 'apple', 5.2);

查询数据

单表查询

  • 查询所有字段

    # 用通配符查询所有列
    mysql> SELECT * from fruits;
    # 用字段名查询指定的列
    mysql> SELECT f_name, s_id FROM fruits;
  • 按某种条件查询 (WHERE的关键字)

        # 可以使用比较符号 = != < <=,查某个区间用BETWEEN AND
    	> SELECT f_name, f_price
        -> FROM fruits
        -> WHERE f_price BETWEEN 2.0 AND 10.0;  # BETWEEN AND 可以用NOT修饰
     
        # 可以使用IN查询指定范围内的记录
    	> SELECT *
        -> FROM fruits
        -> WHERE s_id IN (101, 102) # IN 括号内的条件满足一个即可, 也可以用NOT IN
        -> ORDER BY f_price;
     
        # 可以使用like % _ 来匹配,某种字母模式。
    	> SELECT * FROM fruits
        -> WHERE f_name LIKE 'b%y'; # %匹配多个字符, _ 匹配一个字符。
     
        # 查询空值
    	> SELECT c_id, c_name, c_email FROM customers
        -> WHERE c_email is NULL;
     
        # AND OR 多条件查询,and 优先级高于OR
    	> SELECT f_name, f_price FROM fruits
        -> WHERE s_id = '101' AND f_price >= 5 AND f_name = 'apple';
     
        # 使查询结果去重。DISTINCT
    mysql> SELECT DISTINCT s_id FROM fruits;
  • 对查询结果进行排序

    mysql> SELECT s_id FROM fruits
        -> ORDER BY s_id;  # 默认升序
    mysql> SELECT s_id FROM fruits
        -> ORDER BY s_id DESC; # 降序
     
    mysql> SELECT f_name, f_id FROM fruits
        -> ORDER BY f_name, f_id; # 多列排序的时候,第一列值相同时,才会按照第二列的要求排序。
  • 聚集函数(不返回实际数据,而是对数据进行某种总结)

    # COUNT(*) 计算总的行数;COUNT(字段) 计算指定列下总行数,将忽略空值。
    	# 查询一共有多少个客户
    	> SELECT COUNT(*) AS cusr_nums FROM customers;
    	# 统计不同订单号中订购的水果种类
    	SELECT o_num, COUNT(f_id) FROM orderitems GROUP BY o_num
    # 还有MAX MIN AVG SUM函数 不举例了
    # 聚合函数一般伴随分组功能来使用
  • 分组查询

    # 创建分组
    	# 统计每个s_id 各有几行
    mysql> SELECT s_id, COUNT(*) AS Total FROM fruits GROUP BY s_id;
    	# GROUP_CONCAT 也是聚合函数,可以将某个分组下的具体字段显示出来
    	> SELECT s_id, GROUP_CONCAT(f_name) AS Names FROM fruits GROUP BY s_id; # 把每个s_id各自对应的水果数显示出来
    # 用HAVING进行过滤,只显示符合条件的分组
    	# 把s_id根据f_name进行分组,并且把f_name多于2的显示出来。
    	> SELECT s_id, GROUP_CONCAT(f_name) FROM fruits GROUP BY s_id HAVING COUNT(*)>2;
    # HAVING 和 WHERE 的区别是:WHERE在分组之前用来过滤记录,HAVING在分组之后选择记录。WHERE排除的记录不再出现在分组中。
     

连接查询

两个或多个表中存放相同意义的字段时,进行连接查询

  • 连接通过表之间的关联字段组合数据;常见做法是让一张表的外键引用另一张表的主键。
  • 内连接查询:利用比较运算符对表之间某几列数据进行比较,列出与连接条件匹配的数据行 基于相等匹配。
# 两个表都有s_id,查找两个表里面都有的s_id 对应的一些内容
# 这是普通的查询语句
mysql> SELECT fruits.s_id, s_name, f_name, f_price
    -> FROM fruits, suppliers 
    -> WHERE fruits.s_id = suppliers.s_id;
#这是内连接的语句 限定条件用ON  基于相等测试
mysql> SELECT fruits.s_id, s_name, f_name, f_price
    -> FROM fruits INNER JOIN suppliers
    -> ON fruits.s_id = suppliers.s_id;
# 自连接 把自己跟自己连成一个表 用别名区分
  • 外连接查询 不光查找符合连接条件的 还会显示出某些一个表有一个表没有的

    左连接 左表为主表,所有行都会显示 不匹配的行显示空值;右连接同理。

# 想找左边表有但是右边表没有的
mysql> SELECT customers.c_id, orders.o_num
    -> FROM customers LEFT OUTER JOIN orders
    -> ON customers.c_id = orders.c_id;

内连接 vs 外连接

  • 内连接(inner join):取出两张表中匹配到的数据,匹配不到的不保留
  • 外连接(outer join):取出连接表中匹配到的数据,匹配不到的也会保留,其值为NULL

子查询

一个查询嵌套在另一个查询里面,先执行子查询,再以子查询的结果作为外部查询的范围

ANY SOME ALL IN EXISTS 关键字

# ANY 表示只要num1中符合 这个数大于 num2中随便一个数 (num2中存在比num1小的就行)
SELECT num1 FROM tbl1 WHERE num1 > ANY (SELECT num2 FROM tbl2);
# ALL 表示num1中符合 这个数大于 num2中全部数 
SELECT num1 FROM tbl1 WHERE num1 > ALL (SELECT num2 FROM tbl2);
# EXISTS 只要是后面的子查询为TRUE 就执行父查询;也可以用NOT EXISTS
# EXISTS 只取决于是否返回行 不取决于行的内容 所以子查询返回啥内容都行
SELECT * FROM fruits
WHERE f_price > 10.7 
AND EXISTS (SELECT * FROM suppliers WHERE s_id=107);
# IN 返回给外层一个数据列 以供比较
SELECT s_id, f_name FROM fruits
WHERE s_id IN 
(SELECT s1.s_id FROM suppliers AS s1 WHERE s1.s_city='Tianjin');

合并查询结果

UNION / UNION ALL 将多条查询结果合并;各查询的列数必须相同,对应列的数据类型应兼容。

# UNION 默认去重;UNION ALL 保留重复行。
SELECT * FROM fruits WHERE f_price < 9
UNION ALL
SELECT * FROM fruits WHERE s_id IN (101,103);

LeetCode 题目

LC176 第二高的薪水

  • 思路 先排序 去重 (DISTINCT) 跳过第一个找第二个(limit m,n 跳过前m个,读取前n个)

    如果是空值就返回NULL ifNULL(a,b) a是NULL就返回b,a不是NULL就返回a。

SELECT IFNULL(
    (SELECT DISTINCT salary FROM Employee ORDER BY salary DESC LIMIT 1, 1),
    NULL
) AS SecondHighestSalary;

LC197 上升的温度

DATEDIFF(a, b) 返回日期 a 与 b 相差的天数。


相关笔记