mysql組合表表達式union,union distinct,union all詳解

1 union簡介
    UNION屬於集合運算符(set operator)允許我們把多個表表達式組合到一個複合表表達式中,它把一個表表達式的結果放在另一個表表達式的下面,在mysql數據庫中提供了UNION和UNION ALL關鍵字,列於每個SELECT語句的對應位置的被選擇的列應具有相同的類型。在第一個SELECT語句中被使用的列名稱也被用於結果的列名稱。
    如果UNION不使用關鍵詞ALL,則所有返回的行都是唯一的,如同已經對整個結果集合使用了DISTINCT。如果指定了ALL,則會從所有用過的SELECT語句中得到所有匹配的行。DISTINCT關鍵詞是一個自選詞,不起任何作用,但是根據SQL標準的要求,在語法中允許採用。也可以在同一查詢中混合UNION ALL和UNION DISTINCT。被混合的UNION類型按照這樣的方式對待,即DISTICT共用體覆蓋位於其左邊的所有ALL共用體。DISTINCT共用體可以使用UNION DISTINCT明確地生成,或使用UNION(後面不加DISTINCT或ALL關鍵詞)隱含地生成。
2 union語法
SELECT column, ...FROM table1
UNION [ALL | DISTINCT]
SELECT column, ...FROM table2
[UNION [ALL | DISTINCT]
SELECT column, ...FROM table3]
    union:用於合併兩個或多個 SELECT 語句的結果集,並消去表中任何重複行。
    union distinct:同union
    union all:用於合併兩個或多個 SELECT 語句的結果集,保留表中重複行。

3 使用union的規則

    3.1 所有相關表表達式的select語句必須具有相同數目的表達式,並且放在一個表表達式下面的表表達式相同或可比較的數據類型。注意:如果兩個數據類型相同或者如果表達式可以通過一個隱式條件轉換爲相同的數據類型,那麼他們是可比較的。
    3.2 來自多張表的數據,多次sql語句取出的列名可以不一致,但最終列名以第一個sql語句的列名爲準。
    3.3 order by只能最後的表表達式之後指定。在所有中間結果已經組合進來以後,排序對整個最終結果執行。
    3.4 select 子句不必包含distinct(但允許),因爲使用union的時候,mysql自動從最終結果中移除重複的行。
4 創建測試表及數據初始化

    4.1 創建測試表

CREATE   TABLE PLAYERS
        (PLAYERNO       INTEGER      NOT NULL,
         NAME           CHAR(15)     NOT NULL,
         INITIALS       CHAR(3)      NOT NULL,
         BIRTH_DATE     DATE                 ,
         SEX            CHAR(1)      NOT NULL,
         JOINED         SMALLINT     NOT NULL,
         STREET         VARCHAR(30)  NOT NULL,
         HOUSENO        CHAR(4)              ,
         POSTCODE       CHAR(6)              ,
         TOWN           VARCHAR(30)  NOT NULL,
         PHONENO        CHAR(13)             ,
         LEAGUENO       CHAR(4)              ,
         PRIMARY KEY    (PLAYERNO));
CREATE   TABLE PENALTIES
        (PAYMENTNO      INTEGER      NOT NULL,
         PLAYERNO       INTEGER      NOT NULL,
         PAYMENT_DATE   DATE         NOT NULL,
         AMOUNT         DECIMAL(7,2) NOT NULL,
         PRIMARY KEY    (PAYMENTNO));
    注:表PLAYERS爲球員信息表,表PENALTIES爲球員罰款記錄表

    4.2 插入測試數據

INSERT INTO PLAYERS VALUES (2, 'Everett', 'R', '1948-09-01', 'M', 1975, 'Stoney Road','43', '3575NH', 'Stratford', '070-237893', '2411');
INSERT INTO PLAYERS VALUES (6, 'Parmenter', 'R', '1964-06-25', 'M', 1977, 'Haseltine Lane','80', '1234KK', 'Stratford', '070-476537', '8467');
INSERT INTO PLAYERS VALUES (7, 'Wise', 'GWS', '1963-05-11', 'M', 1981, 'Edgecombe Way','39', '9758VB', 'Stratford', '070-347689', NULL);
INSERT INTO PLAYERS VALUES (8, 'Newcastle', 'B', '1962-07-08', 'F', 1980, 'Station Road','4', '6584WO', 'Inglewood', '070-458458', '2983');
INSERT INTO PLAYERS VALUES (27, 'Collins', 'DD', '1964-12-28', 'F', 1983, 'Long Drive','804', '8457DK', 'Eltham', '079-234857', '2513');
INSERT INTO PLAYERS VALUES (28, 'Collins', 'C', '1963-06-22', 'F', 1983, 'Old Main Road','10', '1294QK', 'Midhurst', '010-659599', NULL);
INSERT INTO PLAYERS VALUES (39, 'Bishop', 'D', '1956-10-29', 'M', 1980, 'Eaton Square','78', '9629CD', 'Stratford', '070-393435', NULL);
INSERT INTO PLAYERS VALUES (44, 'Baker', 'E', '1963-01-09', 'M', 1980, 'Lewis Street','23', '4444LJ', 'Inglewood', '070-368753', '1124');
INSERT INTO PLAYERS VALUES (57, 'Brown', 'M', '1971-08-17', 'M', 1985, 'Edgecombe Way','16', '4377CB', 'Stratford', '070-473458', '6409');
INSERT INTO PLAYERS VALUES (83, 'Hope', 'PK', '1956-11-11', 'M', 1982, 'Magdalene Road','16A', '1812UP', 'Stratford', '070-353548', '1608');
INSERT INTO PLAYERS VALUES (95, 'Miller', 'P', '1963-05-14', 'M', 1972, 'High Street','33A', '5746OP', 'Douglas', '070-867564', NULL);
INSERT INTO PLAYERS VALUES (100, 'Parmenter', 'P', '1963-02-28', 'M', 1979, 'Haseltine Lane','80', '6494SG', 'Stratford', '070-494593', '6524');
INSERT INTO PLAYERS VALUES (104, 'Moorman', 'D', '1970-05-10', 'F', 1984, 'Stout Street','65', '9437AO', 'Eltham', '079-987571', '7060');
INSERT INTO PLAYERS VALUES (112, 'Bailey', 'IP', '1963-10-01', 'F', 1984, 'Vixen Road','8', '6392LK', 'Plymouth', '010-548745', '1319');

INSERT INTO PENALTIES VALUES (1,  6, '1980-12-08',100);
INSERT INTO PENALTIES VALUES (2, 44, '1981-05-05', 75);
INSERT INTO PENALTIES VALUES (3, 27, '1983-09-10',100);
INSERT INTO PENALTIES VALUES (4,104, '1984-12-08', 50);
INSERT INTO PENALTIES VALUES (5, 44, '1980-12-08', 25);
INSERT INTO PENALTIES VALUES (6,  8, '1980-12-08', 25);
INSERT INTO PENALTIES VALUES (7, 44, '1982-12-30', 30);
INSERT INTO PENALTIES VALUES (8, 27, '1984-11-12', 75);
5 實例分析

    5.1 union

    獲取那些來自Inglewood和來自Plymouth的每個球員的號碼和城市。

select playerno, town 
from PLAYERS 
where town = 'Inglewood' 
union 
select playerno, town 
from PLAYERS 
where town = 'Plymouth';

    如果union左右兩張表爲同一表,也可用or代替,爲不同表則只能使用union,如下兩個例子:

    兩表相同

select playerno, town 
from PLAYERS 
where town = 'Inglewood' 
or
town = 'Plymouth';

    兩表不同

select birth_date as dates 
from PLAYERS 
union 
select payment_date 
from PENALTIES;

    5.2 union all

    union all與union的唯一區別是,當我們使用union重複的行會自動移除,使用union all,則保留重複的行。

select joined 
from PLAYERS 
where town = 'Stratford' 
union all 
select joined 
from PLAYERS 
where town = 'Inglewood';

6 注意事項

    6.1 union與union all的效率

    從效率上說,UNION ALL 要比UNION快很多。UNION ALL只是簡單的將兩個結果合併後就返回。這樣,如果返回的兩個結果集中有重複的數據,那麼返回的結果集就會包含重複的數據了。UNION在進行錶鏈接後會篩選掉重複的記錄,所以在錶鏈接後會對所產生的結果集進行排序運算,刪除重複的記錄再返回結果。如果可以確認合併的兩個結果集中不包含重複的數據的話,那麼就使用UNION ALL。

****************************************************************************************
    原文地址:http://blog.csdn.net/jesseyoung/article/details/40427849
    博客主頁:http://blog.csdn.net/jesseyoung
****************************************************************************************
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章