集合问题
构建数据集
sql
CREATE TABLE t_users(user_id INT, uname CHAR(20), upwd INT, age INT);

sql
CREATE TABLE t_roles(r_id INT, r_name VARCHAR(20),remarks VARCHAR(50));

PRIMARY和UNIQUE的区别:
唯一约束UNIQUE:不能重复; 主键PRIMARY(自带唯一索引):不能重复; 主键不能为null, 一张表只能有一个主键;

user_id是PRIMARY主键,不能为null,uname是UNIQUE可以为NULL但是不能重复

INNER JOIN的另一种写法
从两个表中调用数据,取条件为两列相等
等值查询,取交集
sql
select * from t_users u , t_roles r where u.`rid` = r.`r_id`; # 等值查询,取交集;
select * from t_users u inner join t_roles r on u.`rid` = r.`r_id`; # 内连接查询,取交集;

从两个TABLE中同时取数据的结果就是,会拿着左表中每一行去和右表中每一行进行组合,穷举组合。
sql
#39. 笛卡尔积,没有关联条件;全是重复的数据,应该避免; 6 * 9 = 54
select * from t_users u , t_roles r ;
求两个集合的并集
用两个集合的LEFT JOIN 和 RIGHT JOIN 的结果做UNION
sql
SELECT * FROM t_users u LEFT JOIN t_roles r ON u.`rid`=r.`r_id`
UNION
SELECT * FROM t_users u RIGHT JOIN t_roles r ON u.`rid`=r.`r_id`
得到9条数据

不要用UNION ALL,这样并集不去重,中间交叉的部分会被算2次,就是6+9=15条数据
sql
SELECT * FROM t_users u LEFT JOIN t_roles r ON u.`rid`=r.`r_id`
UNION ALL
SELECT * FROM t_users u RIGHT JOIN t_roles r ON u.`rid`=r.`r_id`

其实更高版本的MySQL支持下面这种方式做并集
sql
SELECT * FROM t_user u FULL JOIN t_roles r ON u.`rid`=r.`r_id`;
左半月
先求并集,然后 左边不是null ,右边是null
sql
select * from
(SELECT * FROM t_users u LEFT JOIN t_roles r ON u.`rid` = r.`r_id`
UNION
SELECT * FROM t_users u RIGHT JOIN t_roles r ON u.`rid` = r.`r_id`) t
where t.`r_name` is null and t.`uname` is not null;
右半月
先求并集,然后左边是null,右边不是null
sql
SELECT * FROM
(SELECT * FROM t_users u LEFT JOIN t_roles r ON u.`rid` = r.`r_id`
UNION
SELECT * FROM t_users u RIGHT JOIN t_roles r ON u.`rid` = r.`r_id`) t
WHERE t.`r_name` IS not NULL AND t.`uname` IS NULL;
左半月+右半月
sql
SELECT * FROM
(SELECT * FROM t_users u LEFT JOIN t_roles r ON u.`rid` = r.`r_id`
UNION
SELECT * FROM t_users u RIGHT JOIN t_roles r ON u.`rid` = r.`r_id`) t
WHERE t.`r_name` IS NULL or t.`uname` IS NULL;
-- 更严谨的写法,但是除了这两个集合以外也没别的数据,所以没必要多写。
SELECT * FROM
(SELECT * FROM t_users u LEFT JOIN t_roles r ON u.`rid` = r.`r_id`
UNION
SELECT * FROM t_users u RIGHT JOIN t_roles r ON u.`rid` = r.`r_id`) t
WHERE (t.`r_name` IS NULL AND t.`uname` IS NOT NULL)
or (t.`uname` IS NULL AND t.`r_name` IS NOT NULL);