1. 程式人生 > >012:子查詢和增刪改查

012:子查詢和增刪改查

err eat 多個 cal mat 行數 分類 查詢 同時

一. 子查詢

子查詢就是指在一個select語句中嵌套另一個select語句。同時,子查詢必須包含括號。
MySQL 5.6.x 版本之前,MySQL的子查詢性能較差,但是從5.6開始,不存在性能差的問題。

select a from t1 where a > any(select a from t2);
  1. select a from t1 是外部查詢(outer query)
  2. (select a from t2) 是子查詢(subquery)

一般說來,子查詢嵌套於外部查詢中,可以將兩個或兩個以上的子查詢進行嵌套

1. 子查詢的使用

1.1. ANY / SOME

如果外部查詢的列的結果和子查詢的列的結果比較得到為True的話,則返回比較值為True的(外查詢)的記錄

(gcdb@localhost) 17:37:05 [mytest]> select * from t1;
+------+
| a    |
+------+
|    1 |
|    3 |
|    4 |
|    5 |
|    7 |
+------+
5 rows in set (0.00 sec)

(gcdb@localhost) 17:37:22 [mytest]> select * from t2;
+------+
| a    |
+------+
|    2 |
|    4 |
|    8 |
|   10 |
+------+
4 rows in set
(0.00 sec) (gcdb@localhost) 17:39:33 [mytest]> select a from t1 where a > any(select a from t2); +------+ | a | +------+ | 3 | | 4 | | 5 | | 7 | +------+ 4 rows in set (0.00 sec) -- 這個查詢可以解釋為,t1表內a列的值大於t2表中a列的任意(any)一個值(t1.a > any(t2.a) == true),則返回t1.a的記錄

ANY關鍵詞必須與一個比較操作符一起使用: =

, >, <, >=, <=, <> (這個是!=的意思)

子查詢中SOMEANY是同一個意思

1.2. IN

inANY的一種特殊情況:"in" equals "= any"

(gcdb@localhost) 17:58:21 [mytest]> select a from t1 where a = any(select a from t2); -- t1.a==t2.a 的只有4
+------+
| a    |
+------+
|    4 |
+------+
1 row in set (0.00 sec)

(gcdb@localhost) 17:57:01 [mytest]>  select a from t1 where a in (select a from t2);  -- in的結果等同於 =any 的結果
+------+
| a    |
+------+
|    4 |
+------+
1 row in set (0.00 sec)

select a from s1 where a in (select a in t2);是用的比較多的一種語法

1.3. ALL

如果外部查詢的列的結果和子查詢的列的所有結果比較得到為True的話,則返回比較值為True的(外查詢)的記錄

(gcdb@localhost) 17:55:03 [mytest]> select a from t2 where a >all(select a from t1);
+------+
| a    |
+------+
|    8 |
|   10 |
+------+
2 rows in set (0.00 sec)

ALL關鍵詞必須與一個比較操作符一起使用
NOT IN<> ALL的別名

2. 子查詢的分類

  • 獨立子查詢
    • 不依賴外部查詢而運行的子查詢
    (gcdb@localhost) 18:00:04 [mytest]> select a from t1 where a in (1,2,3,4,5);
    +------+
    | a    |
    +------+
    |    1 |
    |    3 |
    |    4 |
    |    5 |
    +------+
    4 rows in set (0.00 sec)
  • 相關子查詢
    • 引用了外部查詢列的子查詢
    -- 在這個例子中,子查詢中使用到了外部的列t2.a 
    
    (gcdb@localhost) 18:00:48 [mytest]>  select a from t1 where a in (select * from t2 where t1.a = t2.a);
    +------+
    | a    |
    +------+
    |    4 |
    +------+
    1 row in set (0.00 sec)

3. 子查詢的優化

  • MySQL5.6之前
    • MySQL5.6之前,優化器會把子查詢重寫成exists的形式
    select a from t1 where a in (select a from t2); -- 這個是一條獨立的子查詢,時間復雜度 O(M+N)
    --
    -- 經過優化器重寫後
    --
    select a from t1 where exists (select 1 from t2 where t1.a = t2.a); -- 這是相關子查詢,復雜度O(M*N + M)
    • MySQL 5.6之前,部分的子查詢需要重寫成join的形式 (註意表的大小)
    mysql> select t1.a from t1 join t2 on t1.a = t2.a;
    +------+
    | a    |
    +------+
    |    4 |
    +------+
    1 row in set (0.00 sec)
  • MySQL 5.6之後
    MySQL 5.6之後,優化器不會將子查詢重寫exists的形式,而是自動優化,性能有了大幅提升

4. 包含NULL值的NOT IN

mysql> select null in (‘a‘, ‘b‘, null);
+--------------------------+
| null in (‘a‘, ‘b‘, null) |
+--------------------------+
|                     NULL |
+--------------------------+
1 row in set (0.00 sec)

MySQL數據庫的比較操作,除了返回1(True), 0(False)之外,還會返回NULL
NULLNULL的比較,返回的還是NULL

mysql> select null not in (‘a‘, ‘b‘, null);  
+------------------------------+
| null not in (‘a‘, ‘b‘, null) |
+------------------------------+
|                         NULL |  -- null不在(‘a‘, ‘b‘, null)中,返回的還是null,因為有null和null的比較
+------------------------------+
1 row in set (0.00 sec)

mysql> select ‘a‘ not in (‘a‘, ‘b‘, null);  
+-----------------------------+
| ‘a‘ not in (‘a‘, ‘b‘, null) |
+-----------------------------+
|                           0 |  -- a 不在 (‘a‘, ‘b‘, null)中,返回0,即False
+-----------------------------+
1 row in set (0.00 sec)

mysql> select ‘c‘ not in (‘a‘, ‘b‘);
+-----------------------+
| ‘c‘ not in (‘a‘, ‘b‘) |
+-----------------------+
|                     1 |  -- 這個返回值可以理解 ‘c‘不在(‘a‘, ‘b‘)中,返回1,即為True
+-----------------------+
1 row in set (0.00 sec)

mysql> select ‘c‘ not in (‘a‘, ‘b‘, null); 
+-----------------------------+
| ‘c‘ not in (‘a‘, ‘b‘, null) |
+-----------------------------+
|                        NULL | -- 理論上應該是返回1,即True的。但是包含了null值。則返回null
+-----------------------------+
1 row in set (0.00 sec)

對於包含了NULL值的IN操作,總是返回True或者NULL
NOT IN返回NOT True (False)或者NOT NULL (NULL)

--
-- SQL語句一 使用 EXISTS
--
select customerid, companyname 
    from customers as A
    where country = ‘Spain‘ 
        and not exists
            ( select * from orders as B
              where A.customerid = B.customerid );
              
--
-- SQL語句二 使用 IN
--
select customerid, companyname 
    from customers as A
    where country = ‘Spain‘ 
        and customerid not in (select customerid from orders);
              
-----
-- 當結果集合中沒有NULL值時,上述兩條SQL語句查詢的結果是一致的 
-----

--
-- 插入一個NULL值
--
insert into orders(orderid) values (null);

-----
-- SQL語句1 : 返回和之前一致
-- SQL語句2 : 返回為空表,因為子查詢返回的結果集中存在NULL值。not in null 永遠返回False或者NULL
--            此時 where (country = ‘Spain‘ and (False or NULL)) 為 False OR NULL,條件永遠不匹配
-----

--
-- SQL語句2 改寫後
--
select customerid, companyname 
    from customers as A
    where country = ‘Spain‘ 
        and customerid not in (select customerid from orders 
                                where customerid is not null);  -- 增加這個過濾條件,使用is not,而不是<>


--
-- 和 null比較,使用is和is not, 而不是 = 和 <>
--
mysql> select null = null; 
+-------------+
| null = null |
+-------------+
|        NULL |
+-------------+
1 row in set (0.00 sec)

mysql> select null <> null;
+--------------+
| null <> null |
+--------------+
|         NULL |
+--------------+
1 row in set (0.00 sec)

mysql> select null is null; 
+--------------+
| null is null |
+--------------+
|            1 |  -- 返回 True
+--------------+
1 row in set (0.00 sec)

mysql> select null is not  null;
+-------------------+
| null is not  null |
+-------------------+
|                 0 |  -- 返回 False
+-------------------+
1 row in set (0.00 sec)

EXISTS不管返回值是什麽,而是看是否有返回,所以EXISTS中子查詢都是select *select 1等,因為只關心返回是否有行(結果集)


二. INSERT

官方文檔

(gcdb@localhost) 10:46:17 [mytest]> select * from t1;
+------+
| a    |
+------+
|    1 |
|    3 |
|    4 |
|    5 |
|    7 |
+------+
5 rows in set (0.00 sec)

(gcdb@localhost) 10:46:36 [mytest]> insert into t1 values(9);  -- 插入一個值
Query OK, 1 row affected (0.01 sec)

(gcdb@localhost) 10:46:44 [mytest]> insert into t1(a) values(9),(11);    -- 插入多個值,MySQL獨有
Query OK, 2 rows affected (0.00 sec)
Records: 2  Duplicates: 0  Warnings: 0

(gcdb@localhost) 10:47:11 [mytest]> insert into t1(a) select 13;  -- insert XXX select XXX 語法,MySQ獨有
Query OK, 1 row affected (0.00 sec)
Records: 1  Duplicates: 0  Warnings: 0

(gcdb@localhost) 10:53:34 [mytest]> select * from t1;
+------+
| a    |
+------+
|    1 |
|    3 |
|    4 |
|    5 |
|    7 |
|    9 |
|   11 |
|   13 |
+------+
8 rows in set (0.00 sec)

(gcdb@localhost) 10:46:52 [mytest]> create table t3(a int, b int);  -- 有多個列
Query OK, 0 rows affected (0.15 sec)

(gcdb@localhost) 10:47:24 [mytest]> insert into t3 select 12;   -- 沒有指定列,報錯
ERROR 1136 (21S01): Column count doesn‘t match value count at row 1

(gcdb@localhost) 10:47:48 [mytest]> insert into t3(a) select 12;   -- 指定列a
Query OK, 1 row affected (0.00 sec)
Records: 1  Duplicates: 0  Warnings: 0

(gcdb@localhost) 10:48:08 [mytest]> insert into t3(a,b) select 11,12;  -- 不指定列,但是插入值匹配列的個數和類型
Query OK, 1 row affected (0.00 sec)
Records: 1  Duplicates: 0  Warnings: 0

(gcdb@localhost) 10:48:21 [mytest]> select * from t3;
+------+------+
| a    | b    |
+------+------+
|   12 | NULL |
|   11 |   12 |
+------+------+
2 rows in set (0.00 sec)

(gcdb@localhost) 10:49:19 [mytest]> insert into t3 select * from t3;   -- 從t3表中查詢數據並插回t3中
Query OK, 2 rows affected (0.00 sec)
Records: 2  Duplicates: 0  Warnings: 0


(gcdb@localhost) 10:55:49 [mytest]> insert into t3(a) select a from t2;  -- 從t2表中查詢數據並插入到t3(a)中,註意指定列
Query OK, 4 rows affected (0.00 sec)
Records: 4  Duplicates: 0  Warnings: 0

(gcdb@localhost) 10:59:02 [mytest]> select * from t3;
+------+------+
| a    | b    |
+------+------+
|   12 | NULL |
|   11 |   12 |
|   12 | NULL |
|   11 |   12 |
|    2 | NULL |
|    4 | NULL |
|    8 | NULL |
|   10 | NULL |
+------+------+
8 rows in set (0.00 sec)

--
-- 如果想快速增長表格中的數據,可以使用如下方法,使得數據成倍增長
--
mysql> insert into t3 select * from t3;
Query OK, 5 rows affected (0.03 sec)  -- 插入了5列
Records: 5  Duplicates: 0  Warnings: 0

mysql> select * from t3;               
+------+------+
| a    | b    |
+------+------+
|    8 | NULL |
|    8 |    9 |
| NULL |    5 |
| NULL |    4 |
| NULL |    3 |
|    8 | NULL |
|    8 |    9 |
| NULL |    5 |
| NULL |    4 |
| NULL |    3 |
+------+------+
10 rows in set (0.00 sec)

三. DELETE

官方文檔

(gcdb@localhost) 11:02:10 [mytest]> delete from t3 where b is null; -- 根據過濾條件刪除
Query OK, 6 rows affected (0.00 sec)

(gcdb@localhost) 11:02:16 [mytest]> select * from t3;
+------+------+
| a    | b    |
+------+------+
|   11 |   12 |
|   11 |   12 |
+------+------+
2 rows in set (0.00 sec)


(gcdb@localhost) 11:02:48 [mytest]> delete from t3;   -- 刪除整個表
Query OK, 2 rows affected (0.00 sec)

(gcdb@localhost) 11:03:17 [mytest]> select * from t3;
Empty set (0.00 sec)

四. UPDATE

官方文檔

(gcdb@localhost) 11:03:19 [mytest]> insert into t3 select 1,2;
Query OK, 1 row affected (0.00 sec)
Records: 1  Duplicates: 0  Warnings: 0

(gcdb@localhost) 11:03:54 [mytest]> insert into t3 select 2,3;
Query OK, 1 row affected (0.00 sec)
Records: 1  Duplicates: 0  Warnings: 0

(gcdb@localhost) 11:03:58 [mytest]> insert into t3 select 3,4;
Query OK, 1 row affected (0.00 sec)
Records: 1  Duplicates: 0  Warnings: 0

(gcdb@localhost) 11:04:02 [mytest]> select * from t3;
+------+------+
| a    | b    |
+------+------+
|    1 |    2 |
|    2 |    3 |
|    3 |    4 |
+------+------+
3 rows in set (0.00 sec)
(gcdb@localhost) 11:04:30 [mytest]> update t3 set a =10 where a=1;
Query OK, 1 row affected (0.00 sec)
Rows matched: 1  Changed: 1  Warnings: 0

(gcdb@localhost) 11:05:02 [mytest]>  select * from t3;
+------+------+
| a    | b    |
+------+------+
|   10 |    2 |
|    2 |    3 |
|    3 |    4 |
+------+------+
3 rows in set (0.00 sec)

--
-- 關聯後更新
--

(gcdb@localhost) 11:05:07 [mytest]> select * from t2;
+------+
| a    |
+------+
|    2 |      --和t3中的a列2相等
|    4 |
|    8 |
|   10 |      --和t3中的a列10相等
+------+
4 rows in set (0.00 sec)

(gcdb@localhost) 11:06:05 [mytest]> select * from t3;
+------+------+
| a    | b    |
+------+------+
|   10 |    2 |   -- 和t2中的10相等
|    2 |    3 |   -- 和t2中的2相等
|    3 |    4 |
+------+------+
3 rows in set (0.00 sec)

(gcdb@localhost) 11:08:08 [mytest]> update t2 join t3 on t2.a = t3.a  set t2.a=1000;   -- 先得到t2.a=t3.a的結果然後將結果集中的t2.a設置為100
Query OK, 2 rows affected (0.00 sec)
Rows matched: 2  Changed: 2  Warnings: 0

(gcdb@localhost) 11:08:16 [mytest]> select * from t2;
+------+
| a    |
+------+
| 1000 |   -- 該行原先2被更新成100
|    4 |
|    8 |
| 1000 |   -- 該行原先10被更新成100
+------+
4 rows in set (0.01 sec)

五. REPLACE

官方文檔

(gcdb@localhost) 11:18:41 [mytest]> create table t4(a int primary key auto_increment,b int);
Query OK, 0 rows affected (0.01 sec)

(gcdb@localhost) 11:18:47 [mytest]> insert into t4 values(null,1);
Query OK, 1 row affected (0.00 sec)

(gcdb@localhost) 11:19:17 [mytest]> insert into t4 values(null,2);
Query OK, 1 row affected (0.00 sec)

(gcdb@localhost) 11:19:19 [mytest]> insert into t4 values(null,3);
Query OK, 1 row affected (0.00 sec)

(gcdb@localhost) 11:19:22 [mytest]> select * from t4;
+---+------+
| a | b    |
+---+------+
| 1 |    1 |
| 2 |    2 |
| 3 |    3 |
+---+------+
3 rows in set (0.00 sec)

(gcdb@localhost) 11:20:01 [mytest]> insert into t4 values(1,10);    -- error,主鍵值1,重復 
ERROR 1062 (23000): Duplicate entry ‘1‘ for key ‘PRIMARY‘

(gcdb@localhost) 11:20:28 [mytest]> replace into t4 values(1,10);   -- 替換該主鍵對應的值  
Query OK, 2 rows affected (0.00 sec)                                -- 兩行記錄受到影響

(gcdb@localhost) 11:20:54 [mytest]> select * from t4;
+---+------+
| a | b    |
+---+------+
| 1 |   10 |     -- 已經被更新
| 2 |    2 |
| 3 |    3 |
+---+------+
3 rows in set (0.00 sec)

-----
-- replace的原理是:先delete,在insert ;註意:需要delete和insert權限
-----

(gcdb@localhost) 11:24:23 [mytest]> replace into t4 values(5,15);   -- 沒有替換對象時,類似插入效果
Query OK, 1 row affected (0.03 sec)    -- 只影響1行

(gcdb@localhost) 11:24:32 [mytest]> select * from t4;
+---+------+
| a | b    |
+---+------+
| 1 |   10 |
| 2 |    2 |
| 3 |    3 |
| 5 |   15 |         -- 新插入一行
+---+------+
4 rows in set (0.00 sec)

--
-- replace原理更明顯的例子 
--

(gcdb@localhost) 11:24:35 [mytest]> create table t6
    -> (a int primary key,
    -> b int auto_increment,  -- b是auto_increment的int型數據
    -> c int,key(b));
Query OK, 0 rows affected (0.01 sec)


(gcdb@localhost) 11:26:54 [mytest]> insert into t6 values(1,null,10),(2,null,20),(3,null,30);
Query OK, 3 rows affected (0.00 sec)
Records: 3  Duplicates: 0  Warnings: 0

(gcdb@localhost) 11:28:08 [mytest]> select * from t6;  
+---+---+------+
| a | b | c    |    --b類為自增列
+---+---+------+
| 1 | 1 |   10 |   
| 2 | 2 |   20 |
| 3 | 3 |   30 |
+---+---+------+
3 rows in set (0.00 sec)

(gcdb@localhost) 11:29:14 [mytest]> replace into t6 values(1,null,99);
Query OK, 2 rows affected (0.00 sec)

(gcdb@localhost) 11:29:40 [mytest]> select * from t6;
+---+---+------+
| a | b | c    |
+---+---+------+
| 1 | 4 |   99 |    --當a=1時,c列值10被替換為99和b列值3自增加1為4
| 2 | 2 |   20 |
| 3 | 3 |   30 |
+---+---+------+
3 rows in set (0.00 sec)
-----

--
-- insert on duplicate 效果和 replace類似
--
(gcdb@localhost) 11:29:50 [mytest]> select * from t4;
+---+------+
| a | b    |
+---+------+
| 1 |   10 |
| 2 |    2 |
| 3 |    3 |
| 5 |   15 |
+---+------+
4 rows in set (0.00 sec)

(gcdb@localhost) 11:33:31 [mytest]> insert into t4 values(1,1); -- 插入報錯,存在key為1的記錄
ERROR 1062 (23000): Duplicate entry ‘1‘ for key ‘PRIMARY‘

(gcdb@localhost) 11:34:26 [mytest]> insert into t4 values(1,1) on duplicate key update b=1;  -- 帶上on duplicate參數(非SQL標準,不推薦)
Query OK, 2 rows affected (0.00 sec)

(gcdb@localhost) 11:34:31 [mytest]> select * from t4;
+---+------+
| a | b    |
+---+------+
| 1 |    1 |   - 該行的b列從10被替換成1
| 2 |    2 |
| 3 |    3 |
| 5 |   15 |
+---+------+
4 rows in set (0.00 sec)

--
-- insert ignore
--
(gcdb@localhost) 11:34:34 [mytest]>  insert ignore into t4 values(1,1);  -- 忽略重復的錯誤
Query OK, 0 rows affected, 1 warning (0.00 sec)

(gcdb@localhost) 11:36:37 [mytest]> show warnings;
+---------+------+---------------------------------------+
| Level   | Code | Message                               |
+---------+------+---------------------------------------+
| Warning | 1062 | Duplicate entry ‘1‘ for key ‘PRIMARY‘ |
+---------+------+---------------------------------------+
1 row in set (0.00 sec)

六. 關聯更新和行號查詢

  • 關聯更新
(gcdb@localhost) 11:38:36 [mytest]> create table t5 (a int, b int);
Query OK, 0 rows affected (0.14 sec)

(gcdb@localhost) 11:39:38 [mytest]> insert into t5 values(1,1);
Query OK, 1 row affected (0.03 sec)

(gcdb@localhost) 11:39:49 [mytest]> select * from t5;
+------+------+
| a    | b    |
+------+------+
|    1 |    1 |
+------+------+
1 row in set (0.00 sec)

(gcdb@localhost) 11:39:51 [mytest]> update t5 set a= a+1,b=a where a=1;
Query OK, 1 row affected (0.00 sec)
Rows matched: 1  Changed: 1  Warnings: 0

(gcdb@localhost) 11:40:03 [mytest]> select * from t5;
+------+------+
| a    | b    |
+------+------+
|    2 |    2 |  -- SQL Server和Oracle中得到的值是2, 1
+------+------+
1 row in set (0.00 se
  • 顯示行號(RowNumber)
--
-- 方法一
--
(gcdb@localhost) 11:41:08 [mytest]> use employees;
Database changed

(gcdb@localhost) 11:42:15 [employees]> set @rn:=0;   -- 產生 SESSION(會話)級別的變量
Query OK, 0 rows affected (0.00 sec)

(gcdb@localhost) 11:42:21 [employees]> select @rn:=@rn+1 as rownumber, emp_no, gender from employees limit 10;  -- @rn:=1 是賦值的意思
+-----------+--------+--------+
| rownumber | emp_no | gender |
+-----------+--------+--------+
|         1 |  10001 | M      |
|         2 |  10002 | F      |
|         3 |  10003 | M      |
|         4 |  10004 | M      |
|         5 |  10005 | M      |
|         6 |  10006 | F      |
|         7 |  10007 | F      |
|         8 |  10008 | M      |
|         9 |  10009 | F      |
|        10 |  10010 | F      |
+-----------+--------+--------+
10 rows in set (0.00 sec)

--
-- 方法二 (推薦)
--
(gcdb@localhost) 11:42:31 [employees]> select @rn1:=@rn1+1 as rownumber, emp_no, gender from employees, (select @rn1:=0) as a limit 10;
+-----------+--------+--------+
| rownumber | emp_no | gender |
+-----------+--------+--------+
|         1 |  10001 | M      |
|         2 |  10002 | F      |
|         3 |  10003 | M      |
|         4 |  10004 | M      |
|         5 |  10005 | M      |
|         6 |  10006 | F      |
|         7 |  10007 | F      |
|         8 |  10008 | M      |
|         9 |  10009 | F      |
|        10 |  10010 | F      |
+-----------+--------+--------+
10 rows in set (0.00 sec)

-- MySQL 自定義變量,根據每一記錄進行變化的

(gcdb@localhost) 11:44:55 [employees]> select @rn1:=0;
+---------+
| @rn1:=0 |
+---------+
|       0 |  -- 只有一行記錄
+---------+
1 row in set (0.00 sec)

-- 相當於 把 employees 和 (select @rn1:=0)做了笛卡爾積,然後使用@rn1:=@rn + 1,根據每行進行累加

--
-- ":=" 和 "="
--
(gcdb@localhost) 11:42:15 [employees]> set @rn:=0;  -- 賦值為0
Query OK, 0 rows affected (0.00 sec)

(gcdb@localhost) 11:44:55 [employees]> select @rn1:=0;
+---------+
| @rn1:=0 |
+---------+
|       0 |
+---------+
1 row in set (0.00 sec)

(gcdb@localhost) 11:46:37 [employees]> set @a:=100;    -- 賦值為100
Query OK, 0 rows affected (0.00 sec)

(gcdb@localhost) 11:46:54 [employees]> select @a;
+------+
| @a   |
+------+
|  100 |
+------+
1 row in set (0.00 sec)

(gcdb@localhost) 11:49:25 [employees]> select @a=99;  -- 進行比較
+-------+
| @a=99 |
+-------+
|     0 |
+-------+
1 row in set (0.00 sec)
  • 使用子查詢實現RowNumber
  1. 思路
    • 假設當前在第N行記錄,通過主鍵emp_no遍歷有多少行的記錄小於等於當前行,即為當前行的行數
  2. SQL語句

    (gcdb@localhost) 12:07:39 [employees]> SELECT  (SELECT COUNT(1) FROM employees b WHERE b.emp_no <= a.emmp_no ) AS row_number, emp_no,CONCAT(last_name," ",first_name) name,gender,hire_date FROM employees aORDER BY emp_no LIMIT 10;
    +------------+--------+--------------------+--------+------------+
    | row_number | emp_no | name               | gender | hire_date  |
    +------------+--------+--------------------+--------+------------+
    |          1 |  10001 | Facello Georgi     | M      | 1986-06-26 |
    |          2 |  10002 | Simmel Bezalel     | F      | 1985-11-21 |
    |          3 |  10003 | Bamford Parto      | M      | 1986-08-28 |
    |          4 |  10004 | Koblick Chirstian  | M      | 1986-12-01 |
    |          5 |  10005 | Maliniak Kyoichi   | M      | 1989-09-12 |
    |          6 |  10006 | Preusig Anneke     | F      | 1989-06-02 |
    |          7 |  10007 | Zielinski Tzvetan  | F      | 1989-02-10 |
    |          8 |  10008 | Kalloufi Saniya    | M      | 1994-09-15 |
    |          9 |  10009 | Peac Sumant        | F      | 1985-02-18 |
    |         10 |  10010 | Piveteau Duangkaew | F      | 1989-08-24 |
    +------------+--------+--------------------+--------+------------+
    10 rows in set (0.59 sec)
    
    
    -- 假設當前在第5行
    (gcdb@localhost) 12:08:38 [employees]> select  b.emp_no  from employees.employees as b order by b.emp_no limit 5;
    +--------+
    | emp_no |
    +--------+
    |  10001 |
    |  10002 |
    |  10003 |
    |  10004 |
    |  10005 |  -- 第5行的emp_no是10005
    +--------+
    5 rows in set (0.00 sec)
    
    (gcdb@localhost) 12:10:28 [employees]> select  count(*)  from employees.employees as b where b.emp_no<= 10005 order by b.emp_no;
    --查找小於等於5的行數有幾行
    +----------+
    | count(*) |
    +----------+
    |        5 |  -- 小於等於10005的記錄有5行,則5就是10005該行記錄的行號
    +----------+
    1 row in set (0.00 sec)
    
    -- 將該子查詢的結果即可作為RowNumber,子查詢循環多次,不推薦使用。
    
    -- 推薦使用下面這種方法
    (gcdb@localhost) 12:12:01 [employees]> SELECT @a:=@a+1 AS row_number,
        ->         emp_no,CONCAT(last_name," ",first_name) name,gender,hire_date
        ->         FROM employees,(SELECT @a:=0) AS a LIMIT 10;
    +------------+--------+--------------------+--------+------------+
    | row_number | emp_no | name               | gender | hire_date  |
    +------------+--------+--------------------+--------+------------+
    |          1 |  10001 | Facello Georgi     | M      | 1986-06-26 |
    |          2 |  10002 | Simmel Bezalel     | F      | 1985-11-21 |
    |          3 |  10003 | Bamford Parto      | M      | 1986-08-28 |
    |          4 |  10004 | Koblick Chirstian  | M      | 1986-12-01 |
    |          5 |  10005 | Maliniak Kyoichi   | M      | 1989-09-12 |
    |          6 |  10006 | Preusig Anneke     | F      | 1989-06-02 |
    |          7 |  10007 | Zielinski Tzvetan  | F      | 1989-02-10 |
    |          8 |  10008 | Kalloufi Saniya    | M      | 1994-09-15 |
    |          9 |  10009 | Peac Sumant        | F      | 1985-02-18 |
    |         10 |  10010 | Piveteau Duangkaew | F      | 1989-08-24 |
    +------------+--------+--------------------+--------+------------+
    10 rows in set (0.00 sec)

012:子查詢和增刪改查