>데이터 베이스 >MySQL 튜토리얼 >MySQL의 논리적 쿼리에 대해 자세히 알아보기

MySQL의 논리적 쿼리에 대해 자세히 알아보기

青灯夜游
青灯夜游앞으로
2021-09-17 19:35:522249검색

Query는 MySQL에서 가장 자주 사용되는 작업이며 DELETE 및 UPDATE를 구축하는 기반이기도 합니다. 쿼리 처리는 논리적 쿼리와 물리적 쿼리로 나눌 수 있습니다. 오늘은 여러분께 논리적 쿼리를 자세히 소개하겠습니다. 도움이 되셨으면 좋겠습니다!

MySQL의 논리적 쿼리에 대해 자세히 알아보기

MySQL에서는 쿼리가 DELETE와 UPDATE를 구축하는 기반이 되는데, 삭제하거나 업데이트하려면 먼저 이러한 레코드를 찾아야 하므로 쿼리 처리에서는 SELECT가 특히 중요하기 때문입니다. 논리적 쿼리와 물리적 쿼리가 있는데, 논리적 쿼리는 SELECT 문을 실행할 때 어떤 종류의 결과가 생성되어야 하는지를 나타내고, 물리적 쿼리는 MySQL이 이 결과를 어떻게 얻는지 나타냅니다. [관련 권장사항: mysql 동영상 튜토리얼]

이 장에서는 논리 쿼리에 대해 설명합니다.

SQL 문에서는 FROM 문이 먼저 처리되고, LIMIT 문이 마지막에 실행됩니다. GROUP BY, ORDER BY 등 모든 문을 사용하면 아래와 같이 대략 10단계로 나눌 수 있습니다. 작업은 가상 테이블을 생성합니다.

(7) select (8)distinct<select_list>

(1) from <left table>
(3) <join_type> join <right_table>
(2)    on<条件>
(4) where <条件>
(5) group by<字段list>
(6) having<条件>
(9) order by<字段>
(10) limit

실제 사례를 통해 분석해 보겠습니다. 먼저 사용자와 주문이라는 두 개의 테이블을 만듭니다.

mysql> create table user (userId int(11),userName varchar(255),city varchar(255), primary key (userId));
Query OK, 0 rows affected, 1 warning (0.05 sec)


mysql> create table orders(orderId int(11) ,userId int(11) ,primary key (orderId));
Query OK, 0 rows affected, 2 warnings (0.05 sec)

데이터를 삽입하세요.

insert user values(1,"张三","内蒙");
insert user values(2,"李四","内蒙");
insert user values(3,"王五","北京");
insert user values(4,"迪迦","西藏");
insert user values(5,"金甲战士","内蒙");

insert orders values(10001,1);
insert orders values(10002,1);
insert orders values(10003,4);
insert orders values(10004,1);
insert orders values(10005,1);
insert orders values(10006,4);
insert orders values(10007,2);

자, 이제 주문량이 3개 미만인 내몽골 사용자를 쿼리해 보겠습니다. SQL은 다음과 같습니다.

mysql> select userName,count(orders.orderId) as total from user 
left join orders on user.userId = orders.userId 
where city="内蒙" 
group by user.userId 
having count(orders.orderId)<3 
order by total desc;
+--------------+-------+
| userName     | total |
+--------------+-------+
| 李四         |     1 |
| 金甲战士     |     0 |
+--------------+-------+
2 rows in set (0.00 sec)

데이터와 SQL이 있는데 구체적인 프로세스를 분석해보겠습니다.

1. 데카르트 곱

가장 먼저 해야 할 일은 FROM 문 전후에 두 테이블의 데카르트 곱을 수행하는 것입니다. 예를 들어 집합 A={a, b} 및 집합 B={0, 1, 2}라고 가정하면 두 집합의 데카르트 곱은 {(a, 0), (a, 1), ( a , 2), (b, 0), (b, 1), (b, 2)}.

따라서 위의 데이터에 대응하여 최종적으로 35행의 데이터를 포함하는 가상 테이블 VT1이 생성됩니다. ㅋㅋㅋ 0 1

11장산내몽고 1000211Zhang San내몽골1000341Zhang San 내몽골 1000511 장삼내몽고1000611Zhang San내몽고1000541장산 내몽고 100072# 내몽골1000115황금 갑옷 전사내몽고100021

2. ON过滤器

下一步,通过ON后面的添加过滤掉不需要的数据,在上述SQL中,条件是user.userId = orders.userId ,所以通过上面生成的虚拟表VT1,除去不相关的数据,生成新的虚拟表VT2,最终的结果如下。

+--------+--------------+--------+---------+--------+
| userId | userName     | city   | orderId | userId |
+--------+--------------+--------+---------+--------+
|      1 | 张三         | 内蒙   |   10005 |      1 |
|      1 | 张三         | 内蒙   |   10004 |      1 |
|      1 | 张三         | 内蒙   |   10002 |      1 |
|      1 | 张三         | 内蒙   |   10001 |      1 |
|      2 | 李四         | 内蒙   |   10007 |      2 |
|      3 | 王五         | 北京   |    NULL |   NULL |
|      4 | 迪迦         | 西藏   |   10006 |      4 |
|      4 | 迪迦         | 西藏   |   10003 |      4 |
|      5 | 金甲战士     | 内蒙   |    NULL |   NULL |
+--------+--------------+--------+---------+--------+

3.添加外部行

这一步只有在连接类型为OUTER JOIN才发生。

LEFT OUTER JOIN把左表记为保留表,RIGHT OUTER JOIN把右表作为保留表,FULL OUTER JOIN表示都作为保留表,添加外部行的工作就是在上一步的基础上添加保留表中被过滤条件过滤掉的数据,非保留表的数据被赋值NULL。

最终生成下面的结果,记为虚拟表VT3。

+--------+--------------+--------+---------+--------+
| userId | userName     | city   | orderId | userId |
+--------+--------------+--------+---------+--------+
|      1 | 张三         | 内蒙   |   10005 |      1 |
|      1 | 张三         | 内蒙   |   10004 |      1 |
|      1 | 张三         | 内蒙   |   10002 |      1 |
|      1 | 张三         | 内蒙   |   10001 |      1 |
|      2 | 李四         | 内蒙   |   10007 |      2 |
|      3 | 王五         | 北京   |    NULL |   NULL |
|      4 | 迪迦         | 西藏   |   10006 |      4 |
|      4 | 迪迦         | 西藏   |   10003 |      4 |
|      5 | 金甲战士     | 内蒙   |    NULL |   NULL |
+--------+--------------+--------+---------+--------+

4. WHERE过滤器

这一步很简单,条件为city="内蒙" ,即只保留下city为内蒙的列,并生成新的虚拟表VT4。最终结果如下。

+--------+--------------+--------+---------+--------+
| userId | userName     | city   | orderId | userId |
+--------+--------------+--------+---------+--------+
|      1 | 张三         | 内蒙   |   10005 |      1 |
|      1 | 张三         | 内蒙   |   10004 |      1 |
|      1 | 张三         | 内蒙   |   10002 |      1 |
|      1 | 张三         | 内蒙   |   10001 |      1 |
|      2 | 李四         | 内蒙   |   10007 |      2 |
|      5 | 金甲战士     | 内蒙   |    NULL |   NULL |
+--------+--------------+--------+---------+--------+

5. GROUP BY 分组

这步将上一个步骤进行分组,并生成新的虚拟表VT5,结果如下。

+--------+--------------+--------+
| userId | userName     | city   |
+--------+--------------+--------+
|      1 | 张三         | 内蒙   |
|      2 | 李四         | 内蒙   |
|      5 | 金甲战士     | 内蒙   |
+--------+--------------+--------+

6.HAVING筛选

分完组,我们就可以筛选了,选出count(orders.orderId)<3 的数据即可,最终结果如下。

| userId | userName     | city   | count(orders.orderId) |
+--------+--------------+--------+-----------------------+
|      2 | 李四         | 内蒙   |                     1 |
|      5 | 金甲战士     | 内蒙   |                     0 |
+--------+--------------+--------+-----------------------+

7.处理SELECT列表

虽然SELECT是查询中最先被指定的部分,但是直到这里才真正进行处理,在这一步,将SELECT中指定的列从上一步产生的虚拟表中选出。

8.应用DISTINCT

如果查询语句中存在DISTINCT子句,则会创建一张内存临时表,这张内存临时表的表结构和上一步产生的虚拟表一样,不同的是对进行DISTINCT操作的列增加了一个唯一索引,以此来去除重复数据。

另外对使用了GROUP BY语句的查询,再使用DISTINCT是多余的,因为已经进行了分组,不会移除任何行。

9.排序和LIMIT

最后就是排序,返回新的虚拟表。结果如下。

+--------------+-------+
| userName     | total |
+--------------+-------+
| 李四         |     1 |
| 金甲战士     |     0 |
+--------------+-------+

但是在本例子中没有使用到LIMIT,如果使用到了,那么则从选出指定位置开始的指定行数,

原文地址:https://juejin.cn/post/7000739902937628679

作者:i听风逝夜

更多编程相关知识,请访问:编程视频!!

위 내용은 MySQL의 논리적 쿼리에 대해 자세히 알아보기의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

성명:
이 기사는 juejin.cn에서 복제됩니다. 침해가 있는 경우 admin@php.cn으로 문의하시기 바랍니다. 삭제