文件首頁
MySQL 8.4 參考手冊
相關文件 下載本手冊
PDF (US Ltr) - 39.9Mb
PDF (A4) - 40.0Mb
Man Pages (TGZ) - 258.5Kb
Man Pages (Zip) - 365.5Kb
Info (Gzip) - 4.0Mb
Info (Zip) - 4.0Mb


MySQL 8.4 參考手冊  /  ...  /  衍生表格

15.2.15.8 衍生表格

本節討論衍生表格的一般特性。關於以 LATERAL 關鍵字開頭的側向衍生表格,請參閱第 15.2.15.9 節,「側向衍生表格」

衍生表格是在查詢 FROM 子句範圍內產生表格的運算式。例如,SELECT 陳述式 FROM 子句中的子查詢就是衍生表格。

SELECT ... FROM (subquery) [AS] tbl_name ...

JSON_TABLE() 函數會產生表格,並提供另一種建立衍生表格的方法。

SELECT * FROM JSON_TABLE(arg_list) [AS] tbl_name ...

[AS] tbl_name 子句是必要的,因為 FROM 子句中的每個表格都必須有一個名稱。衍生表格中的任何欄位都必須具有唯一的名稱。或者,tbl_name 後面可以加上一個括號括住的名稱清單,用於衍生表格的欄位。

SELECT ... FROM (subquery) [AS] tbl_name (col_list) ...

欄位名稱的數量必須與表格欄位的數量相同。

為了說明,假設您有這個表格:

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;

結果

+------+------+------+
| sb1  | sb2  | sb3  |
+------+------+------+
|    2 | 2    |    4 |
+------+------+------+

這是另一個範例:假設您想知道分組表格的一組總和的平均值。這不會起作用:

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) 在外部查詢中被識別。

衍生表格的欄位名稱來自其選取清單。

mysql> SELECT * FROM (SELECT 1, 2, 3, 4) AS dt;
+---+---+---+---+
| 1 | 2 | 3 | 4 |
+---+---+---+---+
| 1 | 2 | 3 | 4 |
+---+---+---+---+

若要明確提供欄位名稱,請在衍生表格名稱後面加上括號括住的欄位名稱清單:

mysql> SELECT * FROM (SELECT 1, 2, 3, 4) AS dt (a, b, c, d);
+---+---+---+---+
| a | b | c | d |
+---+---+---+---+
| 1 | 2 | 3 | 4 |
+---+---+---+---+

衍生表格可以傳回純量值、欄位、列或表格。

衍生表格受限於以下限制:

最佳化器會以 EXPLAIN 不需要實體化它們的方式來判斷衍生表格的資訊。請參閱第 10.2.2.4 節,「使用合併或實體化最佳化衍生表格、檢視參考和通用表格運算式」

在某些情況下,使用 EXPLAIN SELECT 可能會修改表格資料。如果外部查詢存取任何表格,且內部查詢呼叫儲存函數來變更表格的一或多列,則可能會發生這種情況。假設在資料庫 d1 中有兩個表格 t1t2,以及一個會修改 t2 的儲存函數 f1,如下所示建立:

CREATE DATABASE d1;
USE d1;
CREATE TABLE t1 (c1 INT);
CREATE TABLE t2 (c1 INT);
CREATE FUNCTION f1(p1 INT) RETURNS INT
  BEGIN
    INSERT INTO t2 VALUES (p1);
    RETURN p1;
  END;

如以下所示,直接在 EXPLAIN SELECT 中參考該函數對 t2 沒有影響:

mysql> SELECT * FROM t2;
Empty set (0.02 sec)

mysql> EXPLAIN SELECT f1(5)\G
*************************** 1. row ***************************
           id: 1
  select_type: SIMPLE
        table: NULL
   partitions: NULL
         type: NULL
possible_keys: NULL
          key: NULL
      key_len: NULL
          ref: NULL
         rows: NULL
     filtered: NULL
        Extra: No tables used
1 row in set (0.01 sec)

mysql> SELECT * FROM t2;
Empty set (0.01 sec)

這是因為 SELECT 陳述式沒有參考任何表格,這可以在輸出的 tableExtra 欄位中看到。以下巢狀 SELECT 也是如此:

mysql> EXPLAIN SELECT NOW() AS a1, (SELECT f1(5)) AS a2\G
*************************** 1. row ***************************
           id: 1
  select_type: PRIMARY
        table: NULL
         type: NULL
possible_keys: NULL
          key: NULL
      key_len: NULL
          ref: NULL
         rows: NULL
     filtered: NULL
        Extra: 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 參考任何表格,最佳化器也會在子查詢中執行陳述式,結果是 t2 會被修改:

mysql> EXPLAIN SELECT * FROM t1 AS a1, (SELECT f1(5)) AS a2\G
*************************** 1. row ***************************
           id: 1
  select_type: PRIMARY
        table: <derived2>
   partitions: NULL
         type: system
possible_keys: NULL
          key: NULL
      key_len: NULL
          ref: NULL
         rows: 1
     filtered: 100.00
        Extra: NULL
*************************** 2. row ***************************
           id: 1
  select_type: PRIMARY
        table: a1
   partitions: NULL
         type: ALL
possible_keys: NULL
          key: NULL
      key_len: NULL
          ref: NULL
         rows: 1
     filtered: 100.00
        Extra: NULL
*************************** 3. row ***************************
           id: 2
  select_type: DERIVED
        table: NULL
   partitions: NULL
         type: NULL
possible_keys: NULL
          key: NULL
      key_len: NULL
          ref: NULL
         rows: NULL
     filtered: NULL
        Extra: No tables used
3 rows in set (0.00 sec)

mysql> SELECT * FROM t2;
+------+
| c1   |
+------+
|    5 |
+------+
1 row in set (0.00 sec)

衍生表格最佳化也可以用於許多相關的(純量)子查詢。如需更多資訊和範例,請參閱第 15.2.15.7 節,「相關子查詢」