Spec-Zone .ru
спецификации, руководства, описания, API
|
Подзапросы являются законными в a SELECT
оператор FROM
пункт. Фактический синтаксис:
SELECT ... FROM (subquery
) [AS]name
...
[AS]
пункт обязателен, потому что
каждая таблица в a name
FROM
у пункта должно быть имя. Любые столбцы в 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
пункт не может быть связанными подзапросами, если не
использующийся в пределах ON
пункт a JOIN
работа.
Перед MySQL 5.6.3, подзапросами в FROM
пункт выполняется даже для EXPLAIN
оператор (то есть, полученные временные таблицы осуществляются). Это
происходит, потому что запросы на верхнем уровне нуждаются в информации обо всех таблицах во время фазы
оптимизации, и таблице, представленной подзапросом в FROM
пункт недоступен, если
подзапрос не выполняется. С MySQL 5.6.3 оптимизатор определяет информацию о полученных таблицах по-другому, и
материализация их не происходит для EXPLAIN
.
См. Раздел 8.13.16.3, "Оптимизируя
Подзапросы в FROM
Пункт (Полученные Таблицы)".
Возможно при определенных обстоятельствах изменить табличное использование данных EXPLAIN SELECT
. Это может произойти, если внешние доступы запроса, любые таблицы
и внутренний запрос вызывают сохраненную функцию, которая изменяет одну или более строк таблицы. Предположите,
что есть две таблицы t1
и t2
в базе данных d1
, создаваемый как показано здесь:
mysql>CREATE DATABASE d1;
Query OK, 1 row affected (0.00 sec)mysql>USE d1;
Database changedmysql>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)
Теперь мы создаем сохраненную функцию f1
который изменяет t2
:
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>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)
Это то, потому что SELECT
оператор не ссылался ни на какие таблицы, как может быть замечен в table
и Extra
столбцы вывода. Это также верно для
вложенного следующего 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)
Однако, если внешнее 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
оператор такой как один показанный здесь может занять много
времени, чтобы выполниться потому что BENCHMARK()
функция выполняется однажды для каждой строки в t1
:
EXPLAIN SELECT * FROM t1 AS a1, (SELECT BENCHMARK(1000000, MD5(NOW())));