SQL的笛卡尔积简记
摘要:
简单记录一下SQL中的笛卡尔积与简单应用;
1 什么是笛卡尔积?
/*
* 什么是笛卡尔积?
* 笛卡尔积:在SQL中的实现方式就是交叉链接(CROSS join) 所有连接方式都会
* 生成临时笛卡尔积表;笛卡尔积是关系代数里的一个概念,表示两个表中的每一行数据任意组合.
* 在实际应用中,笛卡尔积本身大多没有什么实际应用,只有两张表连接查询时加上限制条件,才会有意义
*/
2 笛卡尔积产生的原因
/*
* 笛卡尔积产生的原因?
* 1 表连接缺少关联条件;
* 2 表连接有关联条件,但是oracle判断用笛卡尔积更快,也会出现笛卡尔积,这个时候要看实际执行速度;
* oracle这样判断,一般是表比较小,这个时候要特别检查表的数据量是不是真的很少,以免oracle因为统计信息错误
* 而误判
*/
3 解决笛卡尔积的方式
/*
* 笛卡尔积的解决方案?
* 1 针对 接缺少关联条件导致的笛卡尔积,一般业务是不会直接这么操作的,如果SQL是这样的需要查看SQL是否正确。
* 2 针对有关联条件, oracle仍然采用了笛卡尔积的方式 有两种情况
2.1 由于ORACLE判断作笛卡尔积,说明两表关联,至少有一张表是小表,查看执行计划的基数 这个指数如果与 实际相同,则建议不作优化修改即可。
2.2 如果查看执行计划的基数与实际基数不同,则由可能是oracle数据误判表的基数,则可采用hint方式,改 变SQL的执行过程。
*/
4 创造笛卡尔积
SELECT * FROM student s,course c
SELECT * from student CROSS JOIN course
##上面两种方式都可以出现笛卡尔积现象
# 查询结果:
# stu_id stu_username stu_password c_id cla_id c_id c_name
1 "1" "张三" "123" "1" "1" "1" "数学"
2 "1" "张三" "123" "1" "1" "2" "语文"
3 "1" "张三" "123" "1" "1" "3" "英语"
4 "1" "张三" "123" "1" "1" "4" "物理"
5 "1" "张三" "123" "1" "1" "5" "化学"
6 "1" "张三" "123" "1" "1" "6" "生物"
7 "2" "李四" "234" "2" "2" "1" "数学"
8 "2" "李四" "234" "2" "2" "2" "语文"
9 "2" "李四" "234" "2" "2" "3" "英语"
10 "2" "李四" "234" "2" "2" "4" "物理"
11 "2" "李四" "234" "2" "2" "5" "化学"
12 "2" "李四" "234" "2" "2" "6" "生物"
13 "3" "王五" "258" "2" "1" "1" "数学"
14 "3" "王五" "258" "2" "1" "2" "语文"
15 "3" "王五" "258" "2" "1" "3" "英语"
16 "3" "王五" "258" "2" "1" "4" "物理"
17 "3" "王五" "258" "2" "1" "5" "化学"
18 "3" "王五" "258" "2" "1" "6" "生物"
19 "4" "赵六" "5689" "3" "1" "1" "数学"
20 "4" "赵六" "5689" "3" "1" "2" "语文"
21 "4" "赵六" "5689" "3" "1" "3" "英语"
22 "4" "赵六" "5689" "3" "1" "4" "物理"
23 "4" "赵六" "5689" "3" "1" "5" "化学"
24 "4" "赵六" "5689" "3" "1" "6" "生物"
25 "5" "孙七" "56896" "[NULL]""3" "1" "数学"
26 "5" "孙七" "56896" "[NULL]""3" "2" "语文"
27 "5" "孙七" "56896" "[NULL]""3" "3" "英语"
28 "5" "孙七" "56896" "[NULL]""3" "4" "物理"
29 "5" "孙七" "56896" "[NULL]""3" "5" "化学"
30 "5" "孙七" "56896" "[NULL]""3" "6" "生物"
31 "7" "悟空" "45899" "4" "2" "1" "数学"
32 "7" "悟空" "45899" "4" "2" "2" "语文"
33 "7" "悟空" "45899" "4" "2" "3" "英语"
34 "7" "悟空" "45899" "4" "2" "4" "物理"
35 "7" "悟空" "45899" "4" "2" "5" "化学"
36 "7" "悟空" "45899" "4" "2" "6" "生物"
37 "8" "李四" "234" "2" "2" "1" "数学"
38 "8" "李四" "234" "2" "2" "2" "语文"
39 "8" "李四" "234" "2" "2" "3" "英语"
40 "8" "李四" "234" "2" "2" "4" "物理"
41 "8" "李四" "234" "2" "2" "5" "化学"
42 "8" "李四" "234" "2" "2" "6" "生物"
43 "9" "王五" "258" "2" "1" "1" "数学"
44 "9" "王五" "258" "2" "1" "2" "语文"
45 "9" "王五" "258" "2" "1" "3" "英语"
46 "9" "王五" "258" "2" "1" "4" "物理"
47 "9" "王五" "258" "2" "1" "5" "化学"
48 "9" "王五" "258" "2" "1" "6" "生物"
发现所有行的数据相互组合出现了上述问题
5 实际中使用
/**
* 一般情况下我们应该避免笛卡尔积的出现,因为如果两张表的数据有一个或一个以上的数据量比较大的时候,就会导致"数 据爆表"
* 但是当两张表的数据都比较小的时候就可以使用笛卡尔积来解决问题.
* */
需要给所有的Employee分配几个权限(Role)
-- 建表语句
create table employees
(
empid int primary key,
empname varchar(20) not null
)
create table role
(
roleid int primary key,
description varchar(50) not null
)
create table emp_role
(
empid int ,
roleid int
)
-- 插入数据
insert into employees values(1,'Jacky')
insert into employees values(2,'Wendy')
insert into employees values(3,'David')
insert into employees values(4,'Lucy');
insert into employees values(5,'Tom');
insert into employees values(6,'Ann');
insert into role values(1,'Create Training')
insert into role values(2,'Training')
insert into role values(3,'Manage Employee')
insert into role values(4,'Manage Deparement')
-- 使用笛卡尔积给用户赋予权限
# 操作前查询一下没有数据
select * from emp_role er
# 操作
INSERT INTO emp_role SELECT empid, roleid FROM employees e
CROSS JOIN roles r WHERE r.roleid IN(1,2)
# 操作后数据
# empid roleid
1 "1" "1"
2 "1" "2"
3 "2" "1"
4 "2" "2"
5 "3" "1"
6 "3" "2"
7 "4" "1"
8 "4" "2"
9 "5" "1"
10 "5" "2"
11 "6" "1"
12 "6" "2"