mysql进阶

本文深入探讨了MySQL中的表关系,包括一对一、一对多、多对多的实现方式,并提供了修改表和复制表的方法。此外,详细介绍了单表查询中的group by、聚合函数、拼接字符串等操作,以及多表连接查询的各种类型,如内连接、左连接等。通过实例讲解,帮助读者深化对MySQL查询的理解。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

mysql表关系

https://www.cnblogs.com/bypp/p/7755307.html

创建Mysql表:User用户表,Order订单表,Orderdetail订单详情,item商品表

一个用户对应多个订单,一个订单只能对应一个用户;一个订单对应多个订单详情,一个订单详情只对应一个订单;一个订单详情只对应一个商品,一个商品可以包括在多个订单详情中;所以,用户和商品之间是多对多关系

CREATE TABLE user (
  id bigint(32) NOT NULL AUTO_INCREMENT COMMENT '客户id(主键)',
  username varchar(32) NOT NULL COMMENT '客户名称',
  birthday date DEFAULT NULL COMMENT '客户生日',
  sex char(1) DEFAULT NULL COMMENT '客户性别',
  address varchar(256) DEFAULT NULL COMMENT '客户地址',
  PRIMARY KEY (id)
) 
CREATE TABLE orders (
  id bigint(32) NOT NULL AUTO_INCREMENT COMMENT '客户id(主键)',
  user_id bigint(32) NOT NULL COMMENT '下单客户id(外键)',
  number varchar(32) NOT NULL COMMENT '订单号',
  createtime datetime NOT NULL COMMENT '创建时间',
  note varchar(32) DEFAULT NULL COMMENT '备注',
  PRIMARY KEY (id),
  KEY FK_user (user_id),
  CONSTRAINT FK_user FOREIGN KEY (user_id) REFERENCES user (id)
) 
CREATE TABLE orderdetail (
  id bigint(32) NOT NULL AUTO_INCREMENT COMMENT 'id(主键)',
  order_id bigint(32) NOT NULL COMMENT '订单id',
  item_id bigint(32) NOT NULL COMMENT '商品id',
  item_num bigint(32) DEFAULT NULL COMMENT '商品购买数量',
  PRIMARY KEY (id),
  KEY order_id (order_id),
  KEY orderdetail_ibfk_2_idx (item_id),
  CONSTRAINT orderdetail_ibfk_1 FOREIGN KEY (order_id) REFERENCES orders (id),
  CONSTRAINT orderdetail_ibfk_2 FOREIGN KEY (item_id) REFERENCES item (id)
) ENGINE=InnoDB AUTO_INCREMENT=18 DEFAULT CHARSET=utf8
CREATE TABLE item (
  id bigint(32) NOT NULL AUTO_INCREMENT COMMENT 'id(主键)',
  name varchar(32) NOT NULL COMMENT '商品名称',
  price float(10,1) NOT NULL COMMENT '商品价格',
  detail text COMMENT '商品描述',
  pic varchar(512) DEFAULT NULL COMMENT '商品图片',
  createtime datetime DEFAULT NULL COMMENT '生产日期',
  PRIMARY KEY (id)
) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=utf8

一对一

一张表的一条记录一定只能与另外一张表的一条记录进行对应,反之亦然。

比如:用户和订单编号

1)表结构设计(建物理表)

方法1:分开两个独立的表
create table wife(
id int primary key,
name varchar(10),
sex char(1)
);

create table husband(
id int primary key,
name varchar(10),
sex char(1),
wid int unique,
constraint foreign key(wid) references wife(id)
);

注意: 通过constraint约束体现一对一

连接: https://www.cnblogs.com/cangqinglang/p/10036680.html

复习与加深,什么是约束条件:

连接: https://blog.youkuaiyun.com/w_linux/article/details/79655073

方法2:合并在一个独立表
create table person(
id int primary key,
name varchar(10),
sex char(1),
wife int,
husband int
);
insert into person values(1,‘小花’,‘0’, 0,3);
insert into person values(2,‘玉芬’,‘0’, 0,4);
insert into person values(3,‘张三’,‘1’, 1,0);
insert into person values(4,‘李四’,‘1’, 2,0);
insert into person values(5,‘王五’,‘0’, 0,0);
insert into person values(6,‘张五’,‘2’, 0,0);

语法:case when then end

连接: https://www.cnblogs.com/anche/p/9038802.html

select name, (case sex when ‘0’ then ‘女’
when ‘1’ then ‘男’
else ‘未知’
end) as 性别, id from person;

通过分别建立视图来体现一对一的关系
create view women as select * from person where sex=‘0’;
create view men as select * from person where sex=‘1’;

查询夫妻信息
1)旧版本
select wife.name as 妻子, husband.name as 丈夫 from wife,husband
where wife.id= husband.id;
2)新版本(96):关联(效率更高)
select wife.name as 妻子, husband.name as 丈夫 from husband
INNER JOIN wife ON husband.id = wife.id;

一对多

表A中的一条记录可以与另一张表B中的任意数目的记录相关联,而表b中的某条记录最多与表A有一条相关

比如:订单和订单详情 一个订单对应多个订单详情,一个订单详情只对应一个订单;一个订单详情只对应一个商品,一个商品可以包括在多个订单详情中

# 先创建被关联的表dep                
create table dep(id primary key auto_increment,
                 dep_name char(10),
                 dep_comment char(60))
                 
# 后创建关联表emp              
create table emp(id int primary key auto_increment,
                 name char(15),
                 gender enum('male','femael')not null default 'male',
                 de_id int,
                 foreign key(dep_id),references dep(id));
                 
# 先向被关联的表dep中插入值
insert into dep(dep_name,dep_comment) values('教学组','给学生上课',
                                             '招生组','负责招生计划',
                                             '后勤组','维护教学设备'));
                                             
# 再向关联表emp中插入值
insert into emp(name,gender,de_id) values(('aaa','male',1),
                                          ('bbb','male',2),
                                          ('ccc','female',3),
                                          ('ddd','male',2)
                                            );

一对多查询语句:

连接: https://blog.youkuaiyun.com/hxy19971101/article/details/78032204

多对多

表A中的一个实体可以与表B中的任意数目(零个或多个)记录相关联,表B中的一个记录可以与表A中的任意数目(零个或多个)实体相关联

比如:用户和商品 书籍和出版商

表一:book

idbook_nameprice
1九阴真经100
2葵花宝典200
3吸星大法300

表二:press

idpress_namephone
1人民出版社123
2青春文学234
3北京邮电出版社345

一本书可以是多个出版社出版的,所以需要单独建一个关系表出来

idbook_idp_id
111
213
321
# 创建表1
create table book(id int primary key auto_increment,
                  book_name char(15),
                  price int(5));
# 创建表2
create table press(id int primary key auto_increment,
                   press_name char(20),
                   phone int(11));                 
# 创建关系表
create table b_p(id int primary key auto_increment,
                 book_id int(3),
                 p_id int(3),
                foreign key(book_id) references book(id) on update cascade on delete cascade,
                foreign key(p_id) references press(id) on update cascade on delete cascade);

# 插入值
insert into book values(1,'九阴真经',100),(2,'九阳神功',200),(3,'吸星大法',300);

insert into press(press_name) values('人民出版社'),('青春文学'),('北京邮电出版社');

insert into b_p(book_id,p_id) values(1,1),(1,3),(2,1);

表关系外键约束: https://www.cnblogs.com/yy20141204bb/p/8405000.html

修改表和复制表

# 修改表名
    alter table 表名 rename 新表名;
    
    
# 增加新字段
    alter table 表名 add 字段名 数据类型[约束条件];
    

# 删除字段
    alter table 表名 drop 字段名
    
    
# 修改字段
    alter table 表名 modify 字段名 数据类型[约束条件];
    
    alter table 表名 change 旧字段名 新字段名 旧数据类型[约束条件];
    
    alter table 表名 change 旧字段名 新字段名 新数据类型[约束条件];
    
    
# 复制表
    create table book_copy select *from book;
    

单表查询

select id,name from emp
    where id >1 and name like'%on%'
    group by dep_id
    having 分组后的过滤条件
    order by 排序依据
    limit n;
group by & 聚合函数
# 设置sql_mode 为 only_full_group_by

select 字段1 from 表名 group by 字段1     # 注意前后两个字段名要相同

# 每个部门员工的最高工资
select post,max(salary) from emp group by post;

select post,min(salary) from emp group by post;

select post,avg(salary) from emp group by post;

select post,sum(salary) from emp group by post;

select post,count(gender) from emp group by post;

select post,avg(salary) from emp where age>=30 group by post;
group_concat & 拼接字符串
select post,group_concat(name) from emp group by post;

select post,group_concat(name,'sb')from emp group by post;

select post,group_concat(name,":",salary)from emp group by post;
concat & as
select concate('姓名',name) from emp ;

select name,salary*12 as annual_salary from emp;

select concate('姓名',name) as 姓名  from emp;
having
# 1. having 的语法给是与where一模一样,但是having是在group by之后进行一步过滤
# 2. where不能用聚合函数,但是having可以用聚合函数

# 统计个部门年龄在30岁以上的员工的平均工资,并且保留平均工资大于10000的部门
select post,avg(salary) from emp
                        where age>=30
                        group by post
                        having avg(salary)>10000;
            
# 强调: having必须在group by后用
distinct
# 去重,执行顺序在having之后
select distinct post,avg(salary) from emp
        where age>=30
        group by post
        having avg(salary)>10000;
order by
select * from emp order by salary;      # 默认升序(asc)排

select * from emp order by salary desc; # 降序排

select * from emp order by age desc,salary asc; # 多个排序标准,

# 统计个部门年龄大于10岁,平均工资大于1000,且升序排列
select distinct post,avg(salary)from emp where age >10 
            group by post
            having avg(salary) > 1000
            order by post;
limit
# 限制显示条数

select * from emp limit 3;

# 选择工资前三的员工信息
select * from emp order by salary desc limit 3;

# 分页显示
select * from emp limit 5,5;
正则匹配
select * from emp where name regexp '^jin.*(n|g)$';

# $表示结束
# regexp关键字

多表连接查询

建表
create table department(id int,name varchar(20));

create table employee(id int primary key auto_increment,
                      name varchar(20),sex enum('male','female')not null default 'male',age intm dep_id int);
笛卡尔积查询
select * from emp,dep where emp.dep_id = dep.id
内连接
select * from emp inner join dep on emp.dep_id = dep.id;
左连接
select * from emp left join dep on emp.dep_id = dep.id;
右连接
select * from right join dep on emp.dep_id = dep.id;
全连接
select * from emp left join dep on emp.dep_id = dep.id
union
select * from right join dep on emp.dep_id = dep.id;
子查询
select * from emp inner join dep on demp.dep_id = dep.id
select name from emp where dep_id = (select id from dep where name = '技术');
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值