13.2.10.8 FROM 절의 서브 쿼리
서브 쿼리는 SELECT
문의 FROM
절에서 합법적입니다. 그 실제 구문은 다음과 같습니다.
SELECT ... FROM ( subquery
) [AS] name
...
FROM
절에 어떤 테이블도 이름을 가지고있을 필요가 있기 때문에 [AS]
절은 필수입니다. name
subquery
선택 목록에 열이 있으면 그것이 고유 한 이름을 가지고 있어야합니다.
설명을 위해 다음과 같은 테이블이 있다고합니다.
CREATE TABLE t1 (s1 INT, s2 CHAR (5), s3 FLOAT);
이 테이블의 예를 사용하여 FROM
절에 서브 쿼리를 사용하는 방법을 보여줍니다.
INSERT INTO t1 VALUES (1, '1', 1.0); INSERT INTO t1 VALUES (2, '2', 2.0); SELECT sb1, sb2, sb3 FROM (SELECT s1 AS sb1, s2 AS sb2, s3 * 2 AS sb3 FROM t1) AS sb WHERE sb1> 1;
결과 : 2, '2', 4.0
.
다음 다른 예입니다. 그룹화 된 테이블에 대한 일련의 합계의 평균을 알고 자합니다. 다음 쿼리는 작동하지 않습니다.
SELECT AVG (SUM (column1)) FROM t1 GROUP BY column1;
다만, 다음의 쿼리는 원하는 정보를 제공합니다.
SELECT AVG (sum_column1) FROM (SELECT SUM (column1) AS sum_column1 FROM t1 GROUP BY column1) AS t1;
서브 쿼리에서 사용되는 컬럼 이름 ( sum_column1
)는 외부 쿼리에서 인식됩니다.
FROM
절의 서브 쿼리는 스칼라, 열, 행 또는 테이블을 반환 할 수 있습니다. FROM
절의 서브 쿼리는 JOIN
작업의 ON
절에서 사용되지 않는 한 상관 서브 쿼리 할 수 없습니다.
MySQL 5.6.3 이전에는 FROM
절의 서브 쿼리는 EXPLAIN
문에 대해서도 실행됩니다 (즉, 파생 된 임시 테이블이 구체화됩니다). 이것은 최적화 단계에서 상위 수준의 쿼리 모든 테이블에 대한 정보가 필요하며 서브 쿼리가 실행되지 않는 한 FROM
절의 서브 쿼리에 의해 표현되는 테이블을 사용할 수 없기 때문에 발생합니다. MySQL 5.6.3의 시점에서는 최적화 파생 테이블에 대한 정보를 다른 방법으로 특정하기 위해 그 실체화가 EXPLAIN
에 대해 발생하지 않습니다. 섹션 8.2.1.18.3 "FROM 절의 서브 쿼리 (파생 테이블)의 최적화" 를 참조하십시오.
특정 상황에서는 EXPLAIN SELECT
를 사용하여 테이블 데이터를 변경할 수 있습니다. 이것은 외부 쿼리가 하나의 테이블에 액세스하고 내부 쿼리가 테이블의 하나 이상의 행을 변경하는 스토어드 함수를 호출하는 경우에 발생할 수 있습니다. 데이터베이스 d1
에 다음과 같이 생성 된 2 개의 테이블 t1
과 t2
가 있다고합니다.
mysql>CREATE DATABASE d1;
Query OK, 1 row affected (0.00 sec) mysql>USE d1;
Database changed mysql>CREATE TABLE t1 (c1 INT);
Query OK, 0 rows affected (0.15 sec) mysql>CREATE TABLE t2 (c1 INT);
Query OK, 0 rows affected (0.08 sec)
여기서 t2
를 변경하는 스토어드 함수 f1
을 만듭니다.
mysql>DELIMITER //
mysql>CREATE FUNCTION f1(p1 INT) RETURNS INT
mysql>BEGIN
mysql>INSERT INTO t2 VALUES (p1);
mysql>RETURN p1;
mysql>END //
Query OK, 0 rows affected (0.01 sec) mysql>DELIMITER ;
다음과 같이 EXPLAIN SELECT
에서이 함수를 직접 참조해도 t2
에는 아무런 영향을주지 않습니다.
mysql>SELECT * FROM t2;
Empty set (0.00 sec) mysql>SELECT * FROM t2;
Empty set (0.00 sec) mysql>EXPLAIN SELECT f1(5);
+----+-------------+-------+------+---------------+------+---------+------+------+----------------+ | id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra | +----+-------------+-------+------+---------------+------+---------+------+------+----------------+ | 1 | SIMPLE | NULL | NULL | NULL | NULL | NULL | NULL | NULL | No tables used | +----+-------------+-------+------+---------------+------+---------+------+------+----------------+ 1 row in set (0.00 sec) mysql>SELECT * FROM t2;
Empty set (0.00 sec)
이것은 출력 table
및 Extra
컬럼에서 알 수 있듯이, SELECT
문이 어떤 테이블도 참조 않았기 때문입니다. 이것은 또한 다음 중첩 된 SELECT
에도 적용됩니다.
mysql>EXPLAIN SELECT NOW() AS a1, (SELECT f1(5)) AS a2;
+----+-------------+-------+------+---------------+------+---------+------+------+----------------+ | id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra | +----+-------------+-------+------+---------------+------+---------+------+------+----------------+ | 1 | PRIMARY | NULL | NULL | NULL | NULL | NULL | NULL | NULL | No tables used | +----+-------------+-------+------+---------------+------+---------+------+------+----------------+ 1 row in set, 1 warning (0.00 sec) mysql>SHOW WARNINGS;
+-------+------+------------------------------------------+ | Level | Code | Message | +-------+------+------------------------------------------+ | Note | 1249 | Select 2 was reduced during optimization | +-------+------+------------------------------------------+ 1 row in set (0.00 sec) mysql>SELECT * FROM t2;
Empty set (0.00 sec) mysql>SELECT * FROM t2;
Empty set (0.00 sec)
그러나 외부 SELECT
가 하나의 테이블을 참조하는 경우 최적화 프로그램은 하위 쿼리 문을 실행합니다.
mysql>EXPLAIN SELECT * FROM t1 AS a1, (SELECT f1(5)) AS a2;
+----+-------------+------------+--------+---------------+------+---------+------+------+---------------------+ | id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra | +----+-------------+------------+--------+---------------+------+---------+------+------+---------------------+ | 1 | PRIMARY | a1 | system | NULL | NULL | NULL | NULL | 0 | const row not found | | 1 | PRIMARY | <derived2> | system | NULL | NULL | NULL | NULL | 1 | | | 2 | DERIVED | NULL | NULL | NULL | NULL | NULL | NULL | NULL | No tables used | +----+-------------+------------+--------+---------------+------+---------+------+------+---------------------+ 3 rows in set (0.00 sec) mysql>SELECT * FROM t2;
+------+ | c1 | +------+ | 5 | +------+ 1 row in set (0.00 sec)
이것은 또한 다음과 같은 EXPLAIN SELECT
문은 t1
의 행마다 1 회 BENCHMARK()
함수가 실행되기 때문에 실행 시간이 오래 걸릴 수 있다는 것도 보여줍니다.
EXPLAIN SELECT * FROM t1 AS a1, (SELECT BENCHMARK (1000000 MD5 (NOW ())));