mysql (얕은 것부터 깊은 것까지)

1. 데이터베이스 분류 및 SQL 분류

  • 데이터베이스는 주로 두 가지 범주로 나뉩 关系型数据库니다 非关系型数据库.

  • 관계형 데이터베이스: MySQL, Oracle, DB2, SQL Server, Postgre SQL

    • 관계형 데이터베이스는 일반적으로 당사에서 생성합니다 很多个二维数据表.
    • 데이터 테이블은 서로 연관되어 一对一、一对多、多对多동등한 관계를 형성합니다.
    • 그런 다음 필요한 데이터를 SQL语句사용할 수 있습니다 .多张表中查询
  • 비관계형 데이터베이스: MongoDB, Redis, Memcached, HBse

    • 비관계형 데이터베이스의 영어 명칭은 실제로 SQL 뿐만 아니라 NoSQL;
    • 간단히 말하면 非关系型数据库比较简单一些,存储数据也会更加自由(복잡한 json 객체를 데이터베이스에 직접 삽입할 수도 있습니다);
  • NoSQL은 해당 관계를 기반으로 하며 Key-Value쿼리 프로세스 중에 전달될 필요가 없습니다 SQL解析.

SQL 문의 분류

  • DDL(데이터 정의 언어): 데이터 정의 언어;
    • DDL 문을 사용하여 데이터베이스나 테이블에 대한 작업(생성, 삭제, 수정 등)을 수행할 수 있습니다.
  • DML(데이터 조작 언어): 데이터 조작 언어;
    • 테이블의 필드는 DML 문을 통해 추가, 삭제, 수정 등이 가능합니다 .
  • DQL(데이터 쿼리 언어): 데이터 쿼리 언어;
    • DQL을 통해 데이터베이스에서 레코드를 쿼리할 수 있습니다. (강조)
  • DCL(데이터 제어 언어): 데이터 제어 언어;
    • 데이터베이스 및 테이블 권한에 대한 관련 액세스 제어 작업을 수행합니다.

2. SQL 데이터 유형

  • MySQL이 지원하는 데이터 유형은 다음과 같습니다 数字类型,日期和时间类型,字符串(字符和字节)类型,空间类型和 JSON数据类型.

  • 숫자 유형

    • 정수 숫자 유형: INTEGER, INT, SMALLINT, TINYINT, MEDIUMINT, BIGINT;
    • 부동 소수점 숫자 유형: FLOAT, DOUBLE (FLOAT는 4바이트, DOUBLE은 8바이트)
    • 정확한 숫자 유형: DECIMAL, NUMERIC (DECIMAL은 NUMERIC의 구현 형식입니다.)
    • 정수형이 차지하는 바이트 수
  • 날짜 유형 :

    • YEARYYYY 형식으로 값 표시
      • 범위는 1901~2155 및 0000입니다.
    • DATE유형은 날짜 부분은 있지만 시간 부분은 없는 값에 사용됩니다.
      • DATE는 YYYY-MM-DD 형식으로 값을 표시합니다.
      • 지원되는 범위는 '1000-01-01' ~ '9999-12-31'입니다.
    • DATETIME날짜 및 시간 부분이 포함된 값을 입력하세요.
      • DATETIME은 'YYYY-MM-DD hh:mm:ss' 형식으로 값을 표시합니다.
      • 지원되는 범위는 1000-01-01 00:00:00 ~ 9999-12-31 23:59:59 입니다.
    • TIMESTAMP데이터 유형은 날짜 및 시간 구성 요소를 모두 포함하는 값에 사용됩니다.
      • TIMESTAMP는 'YYYY-MM-DD hh:mm:ss' 형식으로 값을 표시합니다.
      • 그러나 해당 범위는 UTC 시간 범위입니다: '1970-01-01 00:00:01' ~ '2038-01-19 03:14:07'
    • DATETIME 또는 TIMESTAMP 값에는 최대 마이크로초(6자리) 정밀도의 소수 초가 포함될 수 있습니다.
      • 예를 들어 DATETIME으로 표시되는 범위는 '1000-01-01 00:00:00.000000' ~ '9999-12-31 23:59:59.999999'일 수 있습니다.
  • 문자열 유형

    • CHAR테이블을 생성할 때 유형의 길이는 고정되어 있으며 길이는 0에서 255 사이의 값일 수 있습니다.
      • 쿼리하면 다음 공백이 삭제됩니다.
    • VARCHARtype의 값은 可变长度문자열이며, 길이는 0에서 65535 사이의 값으로 지정할 수 있습니다.
      • 쿼리 시 다음 공백은 삭제되지 않습니다.
  • BLOB 유형

    • 큰 바이너리 유형을 저장하는 데 사용됩니다.
  • 텍스트 유형

    • 큰 문자열 유형을 저장하는 데 사용됩니다.

3. DDL 크루드

3.1 라이브러리 운영

  • 모든 데이터베이스 보기
 SHOW DATABASES
  • 데이터베이스를 사용하다
USE 数据库
  • 현재 사용 중인 데이터베이스 보기
 SELECT DATABASE()
  • 데이터베이스 생성
CREATE DATABASE IF NOT EXISTS 数据库名称
  • 데이터베이스 삭제
DROP DATABASE IF EXIT 数据库名称
  • 데이터베이스의 문자 집합 및 데이터 정렬 수정
ALTER DATABASE bilibili CHARACTER SET = utf8 COLLATE = utf8_unicode_ci;

3.2 테이블 제약

  • 기본 키 제약 조건PRIMARY KEY

    • 테이블에는 각 레코드의 고유성을 구별하기 위해 절대 반복되지 않고 비어 있지 않은 필드가 있어야 합니다. 이 필드는 기본 키입니다.
      • 기본 키는 테이블의 유일한 인덱스입니다 .
      • 이어야 하며 NOT NULL, 설정되지 않은 경우 NOT NULL에는MySQL也会隐式的设置为NOT NULL
      • 기본 키는 PRIMARY KEY(key_part, ...)일반적으로 공동 기본 키라고 부르는 다중 열 인덱스일 수도 있습니다.
  • 오직:UNIQUE

    • UNIQUE제약 조건을 사용하는 필드는 테이블에서 달라야 하며 반복되지 않아야 합니다.
    • UNIQUE 인덱스는 NULL을 포함하는 열이 여러 개의 NULL 값을 가질 수 있도록 허용합니다.
  • 비워둘 수 없음:NOT NULL

    • 일부 필드의 경우 사용자가 값을 삽입해야 하며 비워 둘 수 없습니다. 이 경우 NOT NULL을 사용하여 제한할 수 있습니다.
  • 기본값:DEFAULT

    • 일부 필드의 경우 값이 설정되지 않은 경우 기본값을 제공하려고 합니다. 이 경우 DEFAULT를 사용하여 완료할 수 있습니다.
  • 자동 증가:AUTO_INCREMENT

    • user's 와 같은 값을 설정하지 않고도 일부 필드를 증가시킬 수 있기를 바랍니다 id. 이 경우 AUTO_INCREMENT를 사용하여 완료할 수 있습니다.
  • 외래 키 제약 조건FOREIGN KEY(外键id) REFERENCES brand(被引用的id)
    여기에 이미지 설명을 삽입하세요.

3.3 테이블 작업

  • 모든 데이터시트 보기
SHOW TABLES;
  • 테이블 구조 보기
DESC user;
  • 데이터 테이블 생성
CREATE TABLE IF NOT EXISTS `user`(
  name  VARCHAR(10),
	age INT,
	height DOUBLE
);
  • 테이블 삭제
DROP TABLE IF EXISTS `user`
  • 테이블 이름 수정
ALTER TABLE `user` RENAME TO `t_user` 
  • 생성된 사용자 테이블 최적화
CREATE TABLE IF NOT EXISTS `user`(
   id INT PRIMARY KEY AUTO_INCREMENT,
   name VARCHAR(20) UNIQUE NOT NULL,
   sex INT DEFAULT(0),
   tel VARCHAR(20)
);
  • 테이블 필드 작업
# 1.添加一个新的列
ALTER TABLE `user` ADD `publishTime` DATETIME;
# 2.删除一列数据
ALTER TABLE `user` DROP `updateTime`;
# 3.修改列的名称
ALTER TABLE `user` CHANGE `publishTime` `publishDate` DATE;
# 4.修改列的数据类型
ALTER TABLE `user` MODIFY `id` INT

4 DML 크루드

  • 새 테이블 생성 및 기본 CURD 구현
CREATE TABLE IF NOT EXISTS `t_products`(
	id INT PRIMARY KEY AUTO_INCREMENT,
	title VARCHAR(20) UNIQUE NOT NULL,
	description VARCHAR(200) DEFAULT '',
	price DOUBLE DEFAULT 0,
	publishTime DATETIME
);


-- 插入表数据
INSERT INTO `t_products` (title,description, price,publishTime) VALUES('huawei1000','描述华为',8000.0,'2012-11-9')
INSERT INTO `t_products` (title, description, price, publishTime) VALUES ('华为666', '华为666只要6666', 6666, '2166-06-06');
INSERT INTO `t_products` (title, description, price, publishTime) VALUES ('xiaomi666', 'xiaomi666只要6666', 6666, '2116-06-06');


-- 删除数据
-- 1. 删除表里面的所有数据
DELETE FROM `t_products`
-- 2. 根据条件来(id)删除语句
DELETE FROM `t_products` WHERE id=2 
-- 修改数据表
-- 1. 修改表里面的所有数据
UPDATE `t_products` SET price=888;

-- 2.根据条件修改表里的数据
UPDATE `t_products` SET price=888 WHERE id=5;

-- 3.根据条件修改多个数据
UPDATE `t_products` SET price=999,description='xiaomi666只要999' WHERE id=5

-- 修改数据显示最新的更新时间,并把更新的时间也做一个记录
-- TIMESTAMP数据类型被用于同时包含日期和时间部分的值:
-- CURRENT_TIMESTAMP 记录当前的时间

ALTER TABLE `t_products` ADD `updataTime`
   TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP 

5. DQL(데이터 쿼리 언어)

  • SELECT는 하나 이상의 테이블에서 선택한 행(레코드)을 검색하는 데 사용됩니다.
  • 쿼리 형식은 다음과 같습니다
    여기에 이미지 설명을 삽입하세요.

5.1 단일 테이블 쿼리

CREATE TABLE IF NOT EXISTS `products` (
	id INT PRIMARY KEY AUTO_INCREMENT,
	brand VARCHAR(20),
	title VARCHAR(100) NOT NULL,
	price DOUBLE NOT NULL,
	score DECIMAL(2,1),
	voteCnt INT,
	url VARCHAR(100),
	pid INT
);

--  查询
-- 1.查询所有
SELECT * FROM `products`

--  2. 查询指定的字段 price title 	brand
SELECT price, title,brand FROM `products`
-- 3 别名查询 as  ,同时as关键字也是可以省略...
SELECT price as productsPrice, title productsTitle,brand FROM `products`

-- 条件查询-比较运算符
SELECT*FROM `products` WHERE price<1000 

SELECT*FROM `products` WHERE price=939

SELECT*FROM `products` WHERE brand='小米' 


-- 查询条件,逻辑运算符
-- 1. and 关键字与 && 一样
SELECT*FROM `products` WHERE brand='小米' AND price=939
-- 2. 逻辑或 or 
SELECT*FROM `products` WHERE brand='华为' || price>=8000

-- 区间范围查询
-- 1. 关键字 BETWEEN AND
SELECT*FROM `products` WHERE price>=1000 && price<=2000
SELECT*FROM `products`WHERE price BETWEEN 1000 AND 2000

-- 枚举出多个结果,其中之一 
SELECT*FROM `products` WHERE brand='小米' OR brand='华为'

SELECT*FROM `products` WHERE brand IN('小米','华为')


-- 模糊查询link 与特殊符号 % 与 
-- 1. 查询title以v开头
SELECT * FROM `products` WHERE title LIKE 'v%';

-- 2.查询带M的title
SELECT * FROM `products` WHERE title LIKE '%M%';
-- 3.查询带M的title必须是第三个字符 (前面字符利用  _ )既下划线
SELECT * FROM `products` WHERE title LIKE '__M%';


-- 排序 ORDER BY 
--  DESC:降序排列;
--    ASC:升序排列;
-- 1.价格小于1000 降序
 SELECT * FROM `products` WHERE price < 1000 ORDER BY price ASC
 
 -- 分页查询 用法[LIMIT {[offset,] row_count | row_count OFFSET offset}]
--  1.limit 限制20条数据
 SELECT * FROM `products` LIMIT 20
 
--  2. OFFSET 偏移数据 (重第41条数据开始查询,查询20条)
 SELECT * FROM `products` LIMIT 20 OFFSET 40
--  另外一种写法:offset, row_count
SELECT * FROM `products` LIMIT 40, 20

5.2 집계 쿼리 및 그룹 쿼리

  • 그룹 쿼리에서 Group By일부 제약 조건이 쿼리 결과에 추가되면 다음을 사용할 수 있습니다 HAVING.
-- 1. 计算华为手机的平均价格
SELECT AVG(price) FROM `products` WHERE  brand='华为'
-- 2.所有手机的平均分数
SELECT AVG(score) FROM `products`

-- 3.手机中最低和最高分数
SELECT MAX(score) FROM `products`;
SELECT MIN(score) FROM `products`;
-- 4.计算总投票人数
SELECT SUM(voteCnt) FROM `products`;
--  5.计算 华为手机的个数
SELECT COUNT(*) FROM `products` WHERE brand = '华为'

-- 6. 分组 GROUP BY  
--  6.1 对品牌进行分组
SELECT brand FROM `products` GROUP BY brand
-- 6.2 分组后查看最低和最高的手机价格 
-- ROUND 保留的小数ROUND(AVG(price),2)
SELECT brand,MAX(price),MIN(price) FROM `products` GROUP BY brand
-- 6.3 分组查询后进行价格最大值的约束 HAVING
SELECT brand,MAX(price) AS priceMAX,MIN(price) AS priceMin FROM `products` GROUP BY brand HAVING priceMAX > 4000

5.3 다중 테이블 쿼리 및 외래 키 제약 조건

  • 외래 키가 존재하는 경우 데이터 구문 분석 업데이트 및 삭제
    • RESTRICT(제약조건) : 상위 테이블(즉, 외래키의 소스 테이블)에서 해당 레코드를 삭제할 경우 해당 레코드에 해당 외래키가 있는지 먼저 확인하고, 있으면 삭제가 허용되지 않는다.
    • NO ACTION: RESTRICT와 일치합니다. 즉, 슬레이브 데이터가 존재하는 경우 마스터 데이터를 삭제할 수 없습니다.
    • CASCADE: 레코드가 업데이트되거나 삭제되면 해당 레코드에 연결된 외래 키 레코드가 있는지 확인합니다.
      • 업데이트: 그러면 해당 레코드가 업데이트됩니다.
      • 삭제: 연결된 기록이 함께 삭제됩니다.
    • SET NULL: 레코드가 갱신되거나 삭제될 때 해당 레코드에 연관된 외래키 레코드가 있는지 확인하여 해당 레코드가 있으면 해당 값을 NULL로 설정합니다.
-- 多张表的查询
CREATE TABLE IF NOT EXISTS `t_song`(
  id INT PRIMARY KEY AUTO_INCREMENT,
	name VARCHAR(20) NOT NULL,
	duration INT DEFAULT 0,
	singer VARCHAR(10)
-- 	外键约束 这里的意思是singer_id 是外键约束 约束需要引入brand这个表里面的id
--   singer_id INT,
-- 	FOREIGN KEY(singer_id) REFERENCES brand(id)
);

INSERT INTO `t_song` (name,duration,singer) VALUES('爸爸妈妈',100,'李荣浩') 
INSERT INTO `t_song` (name,duration,singer) VALUES('戒烟',120,'李荣浩') 
INSERT INTO `t_song` (name,duration,singer) VALUES('从前的那个少年',100,'李荣浩') 

-- 2.创建歌手表
CREATE TABLE IF NOT EXISTS `t_singer`(
	id INT PRIMARY KEY AUTO_INCREMENT,
	name VARCHAR(10),
	intro VARCHAR(200)
)
-- 插入数据
INSERT INTO `t_singer` (name, intro) VALUES ('五月天', '五月天,全亚洲代表性摇滚乐团。演出足迹踏遍美国,澳洲以及全亚洲地区.')
INSERT INTO `t_singer` (name, intro) VALUES ('李荣浩', '李荣浩,全亚洲代表歌曲制作。')

-- 3.修改歌曲表
ALTER TABLE `t_song` DROP `singer`;
ALTER TABLE `t_song` ADD `singer_id` INT;


多表查询
-- 4.为了品牌单独创建一张表并插入数据
CREATE TABLE IF NOT EXISTS `brands`(
	id INT PRIMARY KEY AUTO_INCREMENT,
	name VARCHAR(10) UNIQUE NOT NULL,
	website VARCHAR(100),
	worldRank INT
);
INSERT INTO `brands` (name, website, worldRank) VALUES ('华为', 'www.huawei.com', 1);
INSERT INTO `brands` (name, website, worldRank) VALUES ('小米', 'www.mi.com', 10);
INSERT INTO `brands` (name, website, worldRank) VALUES ('苹果', 'www.apple.com', 5);
INSERT INTO `brands` (name, website, worldRank) VALUES ('oppo', 'www.oppo.com', 15);
INSERT INTO `brands` (name, website, worldRank) VALUES ('京东', 'www.jd.com', 3);
INSERT INTO `brands` (name, website, worldRank) VALUES ('Google', 'www.google.com', 8);

-- 4.1外键约束 
   --  为products表添加brand_id 
ALTER TABLE `products` ADD `brand_id` INT
   -- 为外键添加约束 并引用表brand中的id字段  REFERENCES brand(id)=>引用brands中的id
ALTER TABLE `products` ADD FOREIGN KEY (brand_id) REFERENCES brands(id);
-- 4.2 将products中的brand_id关联到brand中的id的值
UPDATE `products` SET `brand_id` = 1 WHERE `brand` = '华为';
UPDATE `products` SET `brand_id` = 4 WHERE `brand` = 'OPPO';
UPDATE `products` SET `brand_id` = 3 WHERE `brand` = '苹果';
UPDATE `products` SET `brand_id` = 2 WHERE `brand` = '小米';
-- 5. 外键约束的情况下修改
UPDATE `brands` SET id=100 WHERE id=1
--  1451 - Cannot delete or update a parent row: a foreign key constraint fails (`music_db`.`products`, CONSTRAINT `products_ibfk_1` FOREIGN KEY (`brand_id`) REFERENCES `brands` (`id`)) 报错误

-- 6. 查看表中的外键
SHOW CREATE TABLE `products`

-- 7. 删除外键 
ALTER TABLE `products` DROP FOREIGN KEY products_ibfk_1;
-- 8 添加外键,当外键删除或者更新时 引用应该删除或者更新
ALTER TABLE `products` ADD FOREIGN KEY (brand_id) REFERENCES brands(id) 
                     ON UPDATE CASCADE 
                     ON DELETE CASCADE;
UPDATE `brands` SET id=100 WHERE id=1

5.4 여러 테이블 간의 연결 쿼리

  • 데이터를 쿼리할 때 데이터가 여러 테이블에 존재하기 때문에 다중 테이블 쿼리를 결합해야 합니다.
  • 예를 들어:
SELECT * FROM `products`, `brand`

여기에 이미지 설명을 삽입하세요.

  • 이때 두 테이블의 모든 데이터가 쿼리되어 총 648개수의 데이터가 검색됩니다.
  • 그러면 첫 번째 테이블의 각 데이터 조각이 두 번째 테이블의 각 데이터 조각과 결합됩니다.
  • 우리가 부르는 이 결과는 笛卡尔乘积다음 直积과 같이 표현됩니다 X*Y.
  • 그러나 위 쿼리 결과의 대부분은 의미가 없고 필요한 내용도 아니므로 다음을 사용하겠습니다.连接查询

5.4.1 왼쪽 링크 쿼리

  • 왼쪽(주로 왼쪽 테이블)에 있는 모든 데이터를 가져오려면
  • 이때, 왼쪽 테이블에 오른쪽 테이블의 id에 해당하는 Brand_id 값이 있는지 여부에 관계없이 왼쪽의 데이터를 쿼리한다는 의미입니다.
  • 완전한 글은 이지만 LEFT [OUTER] JOIN,OUTER可以省略
    여기에 이미지 설명을 삽입하세요.
-- 3.左链接 LEFT [OUTER] JOIN "表" ON 连接条件
-- 这个时候就表示无论左边的表是否有对应的brand_id的值对应右边表的id,左边的数据都会被查询出来;
SELECT * FROM `products` LEFT JOIN `brands` ON products.brand_id=brands.id

-- 3.1 查询不为null有交集的数据

SELECT * FROM `products` LEFT JOIN `brands` ON products.brand_id = brands.id WHERE brands.id IS NOT NULL;

5.4.2 오른쪽 조인 쿼리

- 오른쪽(주로 오른쪽 테이블)의 모든 데이터를 가져오려면 다음을 수행합니다 .

  • 이때 왼쪽 테이블의 Brand_id가 오른쪽 테이블의 id와 일치하는지 여부에 관계없이 오른쪽의 데이터를 쿼리한다는 의미입니다.
  • 완전한 작성 방법은 RIGHT [OUTER] JOIN이지만 OUTER 는 생략 가능합니다.
    여기에 이미지 설명을 삽입하세요.
SELECT * FROM `products` RIGHT JOIN `brands` ON products.brand_id=brands.id

5.4.3 내부 조인

  • 상위 내부 조인은 왼쪽 테이블과 오른쪽 테이블에 해당 데이터 연결이 있음을 의미합니다.
    • CROSS JOIN어느 쪽이든 쓸 수 있습니다 JOIN.
SELECT * FROM `products` JOIN `brands` ON `products`.brand_id = `brands`.id
  • 내부 연결이 작성된 곳
SELECT * FROM `products`, `brand` WHERE `products`.brand_id = `brand`.id
  • 위의 SQL 문 비교
  • 내부 조인은 두 테이블이 연결되면 후속 쿼리 결과를 결정하기 위해 데이터 간의 관계가 제한된다는 것을 의미합니다.
  • Where 조건은 먼저 데카르트 곱을 계산한 다음 데카르트 곱의 데이터를 기반으로 Where 조건을 선택하는 것을 의미합니다.

5.4.4 전체 연결

  • 완전 조인은 SQL 사양에서 사용되지만 FULL JOINMySQL에서는 이를 지원하지 않습니다. UNION이를 달성하려면 다음을 사용해야 합니다.
    여기에 이미지 설명을 삽입하세요.
(SELECT * FROM `products` LEFT JOIN `brands` ON `products`.brand_id = `brands`.id)
UNION
(SELECT * FROM `products` RIGHT JOIN `brands` ON `products`.brand_id = `brands`.id)
(SELECT * FROM `products` LEFT JOIN `brands` ON products.brand_id = brands.id WHERE brands.id IS NULL)
UNION
(SELECT * FROM `products` RIGHT JOIN `brands` ON products.brand_id = brands.id WHERE products.id IS NULL)
  • 조인 쿼리 요약
--  在查询到产品的同时,显示对应的品牌相关的信息,因为数据是存放在两张表中,所以这个时候就需要进行多表查询

-- //1.  这种默认做法会发生这个表的数据与另一个表的数据会相乘 得到 M*N的数据
SELECT * FROM `products`, `brands`;  
-- 2.过滤查询
SELECT * FROM `products`, `brands` WHERE products.brand_id=brands.id;  
-- 3.左链接 LEFT [OUTER] JOIN "表" ON 连接条件
-- 这个时候就表示无论左边的表是否有对应的brand_id的值对应右边表的id,左边的数据都会被查询出来;
SELECT * FROM `products` LEFT JOIN `brands` ON products.brand_id=brands.id

-- 3.1 查询不为null有交集的数据

SELECT * FROM `products` LEFT JOIN `brands` ON products.brand_id = brands.id WHERE brands.id IS NOT NULL;

-- 4. 右连接 RIGHT [OUTER] JOIN "表" ON 连接条件
-- 这个时候就表示无论左边的表中的brand_id是否有和右边表中的id对应,右边的数据都会被查询出来
SELECT * FROM `products` RIGHT JOIN `brands` ON products.brand_id=brands.id

-- 5. 内连接 CROSS JOIN或者 JOIN;
-- 5.1内连接效果和下面where查询效果一样的,但是做法确是不一样的
-- 5.1.1SQL语句一:内连接,代表的是在两张表连接时就会约束数据之间的关系,来决定之后查询的结果;
-- 5.1.2SQL语句二:where条件,代表的是先计算出笛卡尔乘积,在笛卡尔乘积的数据基础之上进行where条件的帅选
SELECT * FROM `products` JOIN `brands` ON `products`.brand_id = `brands`.id
SELECT * FROM `products`, `brands` WHERE `products`.brand_id = `brands`.id;

-- 6. 全连接
--  6.1 SQL规范中全连接是使用FULL JOIN,但是MySQL中并没有对它的支持,我们需要使用 UNION 来实现

(SELECT * FROM `products` LEFT JOIN `brands` ON `products`.brand_id = `brands`.id)
UNION
(SELECT * FROM `products` RIGHT JOIN `brands` ON `products`.brand_id = `brands`.id)


(SELECT * FROM `products` LEFT JOIN `brands` ON products.brand_id = brands.id WHERE brands.id IS NULL)
UNION
(SELECT * FROM `products` RIGHT JOIN `brands` ON products.brand_id = brands.id WHERE products.id IS NULL)

5.5 다대다 테이블 쿼리

참고 기사 다대다 분석

-- 1.多对多关系
-- 1.1. 创建学生表
CREATE TABLE IF NOT EXISTS `students`(
    id INT PRIMARY KEY AUTO_INCREMENT,
    name VARCHAR(20) NOT NULL,
    age INT
);
INSERT INTO `students` (name, age) VALUES('why', 18);
INSERT INTO `students` (name, age) VALUES('tom', 22);
INSERT INTO `students` (name, age) VALUES('lilei', 25);
INSERT INTO `students` (name, age) VALUES('lucy', 16);
INSERT INTO `students` (name, age) VALUES('lily', 20);



-- 1.2. 创建课程表
CREATE TABLE IF NOT EXISTS `courses`(
    id INT PRIMARY KEY AUTO_INCREMENT,
    name VARCHAR(20) NOT NULL,
    price DOUBLE NOT NULL
);

INSERT INTO `courses` (name, price) VALUES ('英语', 100);
INSERT INTO `courses` (name, price) VALUES ('语文', 666);
INSERT INTO `courses` (name, price) VALUES ('数学', 888);
INSERT INTO `courses` (name, price) VALUES ('历史', 80);
INSERT INTO `courses` (name, price) VALUES ('物理', 100);


-- 1.3. 学生选择的课程关系表
CREATE TABLE IF NOT EXISTS `students_select_courses`(
	id INT PRIMARY KEY AUTO_INCREMENT,
	student_id INT NOT NULL,
	course_id INT NOT NULL,
  -- 	外键约束
	FOREIGN KEY (student_id) REFERENCES students(id) ON UPDATE CASCADE ON DELETE CASCADE,
	FOREIGN KEY (course_id) REFERENCES courses(id) ON UPDATE CASCADE ON DELETE CASCADE
);

-- 2 选课情况
-- 2-1 why 选修了 英文和数学
INSERT INTO `students_select_courses` (student_id, course_id) VALUES (1, 1);
INSERT INTO `students_select_courses` (student_id, course_id) VALUES (1, 3);
--  2-2 lilei选修了 语文和数学和历史
INSERT INTO `students_select_courses` (student_id, course_id) VALUES (3, 2);
INSERT INTO `students_select_courses` (student_id, course_id) VALUES (3, 3);
INSERT INTO `students_select_courses` (student_id, course_id) VALUES (3, 4);

-- 3查询数据
--  3.1 所有学生的选课情况(内连接)  students_select_courses(内连接属性)
SELECT * FROM `students` 
JOIN  `students_select_courses` ON students.id= students_select_courses.student_id
JOIN `courses` ON students_select_courses.course_id=courses.id

-- 3.2 别名查询名称
SELECT 
stu.name stuName , cou.name couName 
FROM `students` stu
JOIN  `students_select_courses` ON stu.id= students_select_courses.student_id
JOIN `courses` cou ON students_select_courses.course_id=cou.id

-- 3.3左链接
SELECT 
stu.name stuName , cou.name couName 
FROM `students` stu
LEFT JOIN  `students_select_courses` ON stu.id= students_select_courses.student_id
LEFT JOIN `courses` cou ON students_select_courses.course_id=cou.id

-- 3.4 单个学生选择课程情况 (左连接可以保证,在学生没有选择课的情况也可以显示)
SELECT 
stu.name stuName , cou.name couName 
FROM `students` stu
LEFT JOIN  `students_select_courses` ON stu.id= students_select_courses.student_id
LEFT JOIN `courses` cou ON students_select_courses.course_id=cou.id WHERE stu.id=1

-- 3.5 查询哪些学生没有选择课程
SELECT 
stu.name stuName , cou.name couName 
FROM `students` stu
LEFT JOIN  `students_select_courses` ON stu.id= students_select_courses.student_id
LEFT JOIN `courses` cou ON students_select_courses.course_id=cou.id WHERE cou.id is NULL

-- 3.6查询哪些课程没有被学生选择
SELECT 
stu.name stuName , cou.name couName 
FROM `students` stu
RIGHT JOIN  `students_select_courses` ON stu.id= students_select_courses.student_id
RIGHT JOIN `courses` cou ON students_select_courses.course_id=cou.id WHERE cou.id is NULL

6 쿼리 객체 배열

  • 요구 사항: 다중 테이블 쿼리를 수행할 때 표 1의 데이터는 표 2의 데이터 하위 집합으로 처리됩니다.
  • 요구 사항 2: 여러 테이블을 쿼리할 때 브랜드 정보 테이블은 별도의 개체에 배치되어 제품 테이블에 표시됩니다.
  • 요구 사항 3: 여러 테이블을 쿼리할 경우 학습 강좌 선택 정보가 배열 개체에 배치됩니다.
  • JSON_OBJECT 양도 대상
  • JSON_ARRAYAGG和JSON_OBJECT다대다 배열
-- 1. 单表查询
SELECT * FROM `products` WHERE price>5000
-- 2. 多表查询
SELECT * FROM `products` LEFT JOIN `brands` ON products.brand_id=brands.id
WHERE price>5000

-- 3. 多表查询:品牌信息放到一个单独的对象中
-- 格式 JSON_OBJECT([key, val[, key, val] ...])
SELECT 
products.id as pid,products.title as title,products.price as price,
JSON_OBJECT('id',brands.id,'name',brands.name,'website',brands.website) as brand
FROM `products` LEFT JOIN `brands` ON products.brand_id=brands.id
WHERE price>5000

-- 多对多查询
SELECT * FROM `students` as stu
LEFT JOIN `students_select_courses` as ssc ON ssc.student_id=stu.id
LEFT JOIN `courses` as cu ON ssc.course_id =cu.id WHERE cu.id IS NOT NULL

-- 多对多查询分组合并
-- JSON_ARRAYAGG  转为数组对象
SELECT 
stu.id as id, stu.name as name, stu.age as age,
JSON_ARRAYAGG(JSON_OBJECT('id',cs.id,'name',cs.name,'price',cs.price)) as course
FROM `students` as stu
LEFT JOIN `students_select_courses` as ssc ON ssc.student_id=stu.id
LEFT JOIN `courses` as cs ON ssc.course_id =cs.id WHERE cs.id IS NOT NULL
GROUP BY stu.id

рекомендация

отblog.csdn.net/weixin_46104934/article/details/131886318
рекомендация