<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          SQL中 LEFT JOIN 左表合并去重實用技巧

          共 11074字,需瀏覽 23分鐘

           ·

          2021-10-17 08:20

          點擊關(guān)注上方“SQL數(shù)據(jù)庫開發(fā)”,

          設(shè)為“置頂或星標(biāo)”,第一時間送達(dá)干貨

          SQL專欄

          SQL基礎(chǔ)知識第二版
          SQL高級知識第二版

          zyc88.blog.csdn.net/article/details/83002882

          建表:

          CREATE TABLE `table1` (
            `id` int(11NOT NULL AUTO_INCREMENT,
            `name` varchar(60DEFAULT NULL,
            `age` varchar(200DEFAULT NULL,
            `sponsor_id` varchar(20DEFAULT NULL COMMENT '業(yè)務(wù)發(fā)起人',
            `gmt_create_user` int(11NOT NULL COMMENT '創(chuàng)建人id',
            `gmt_create` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '創(chuàng)建時間',
            `gmt_modified` datetime DEFAULT NULL COMMENT '修改時間',
            `gmt_modified_user` int(11DEFAULT NULL COMMENT '修改人id',
            PRIMARY KEY (`id`)
          ENGINE=InnoDB AUTO_INCREMENT=12 DEFAULT CHARSET=utf8mb4 COMMENT='測試表1';
           
          CREATE TABLE `table2` (
            `kid` int(11NOT NULL AUTO_INCREMENT,
            `name` varchar(60DEFAULT NULL,
            `sponsor_id` varchar(20DEFAULT NULL COMMENT '業(yè)務(wù)發(fā)起人',
            `type` int(11NOT NULL COMMENT '創(chuàng)建人id',
            `gmt_create` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '創(chuàng)建時間',
            `gmt_modified` datetime DEFAULT NULL COMMENT '修改時間',
            `gmt_modified_user` int(11DEFAULT NULL COMMENT '修改人id',
            PRIMARY KEY (`kid`)
          ENGINE=InnoDB AUTO_INCREMENT=12 DEFAULT CHARSET=utf8mb4 COMMENT='測試表2';

          插入數(shù)據(jù):

          INSERT INTO `table1`(`id``name``age``sponsor_id``gmt_create_user``gmt_create``gmt_modified``gmt_modified_user`VALUES (1't1''11''10'1'2018-10-10 20:34:03'NULLNULL);
          INSERT INTO `table1`(`id``name``age``sponsor_id``gmt_create_user``gmt_create``gmt_modified``gmt_modified_user`VALUES (2't2''12''10'2'2018-10-10 20:34:03'NULLNULL);
          INSERT INTO `table1`(`id``name``age``sponsor_id``gmt_create_user``gmt_create``gmt_modified``gmt_modified_user`VALUES (3't3''13''10'3'2018-10-10 20:34:03'NULLNULL);
          INSERT INTO `table1`(`id``name``age``sponsor_id``gmt_create_user``gmt_create``gmt_modified``gmt_modified_user`VALUES (4't4''14''20'4'2018-10-10 20:34:03'NULLNULL);
          INSERT INTO `table2`(`kid``name``sponsor_id``type``gmt_create``gmt_modified``gmt_modified_user`VALUES (1't1''10'1'2018-10-10 20:38:10'NULLNULL);
          INSERT INTO `table2`(`kid``name``sponsor_id``type``gmt_create``gmt_modified``gmt_modified_user`VALUES (2't2''10'1'2018-10-10 20:38:10'NULLNULL);
          INSERT INTO `table2`(`kid``name``sponsor_id``type``gmt_create``gmt_modified``gmt_modified_user`VALUES (3't3''10'1'2018-10-10 20:38:10'NULLNULL);
          INSERT INTO `table2`(`kid``name``sponsor_id``type``gmt_create``gmt_modified``gmt_modified_user`VALUES (4't4''10'1'2018-10-10 20:38:10'NULLNULL);
          INSERT INTO `table2`(`kid``name``sponsor_id``type``gmt_create``gmt_modified``gmt_modified_user`VALUES (5't5''10'1'2018-10-10 20:38:10'NULLNULL);
          INSERT INTO `table2`(`kid``name``sponsor_id``type``gmt_create``gmt_modified``gmt_modified_user`VALUES (6't6''10'1'2018-10-10 20:38:10'NULLNULL);
          INSERT INTO `table2`(`kid``name``sponsor_id``type``gmt_create``gmt_modified``gmt_modified_user`VALUES (7't7''10'2'2018-10-10 20:38:10'NULLNULL);
          INSERT INTO `table2`(`kid``name``sponsor_id``type``gmt_create``gmt_modified``gmt_modified_user`VALUES (8't1''11'1'2018-10-10 20:38:10'NULLNULL);

          查詢異常:

          SELECT
           a.*,
           b.type 
          FROM
           table1 a
           LEFT JOIN table2 b ON a.sponsor_id = b.sponsor_id 
          WHERE
           b.type = 1 
           AND a.sponsor_id = 10;

          簡單說明問題出現(xiàn)的原因:

          MySQL left join 語句格式為:A LEFT JOIN B ON 條件表達(dá)式

          left join 是以A表為基礎(chǔ),A表即左表,B表即右表。

          左表(A)的記錄會全部顯示,而右表(B)只會顯示符合條件表達(dá)式的記錄,如果在右表(B)中沒有符合條件的記錄,則記錄不足的地方為NULL。

          使用left join, A表與B表所顯示的記錄數(shù)為 1:1 或 1:0,A表的所有記錄都會顯示,B表只顯示符合條件的記錄。

          但如果B表符合條件的記錄數(shù)大于1條,就會出現(xiàn)1:n的情況,這樣left join后的結(jié)果,記錄數(shù)會多于A表的記錄數(shù)。

          所以解決辦法 都是從一個出發(fā)點出發(fā),使A表與B表所顯示的記錄數(shù)為 1:1對應(yīng)關(guān)系。

          解決方法:

          使用非唯一標(biāo)識的字段做關(guān)聯(lián)

          1 DISTINCT

          select DISTINCT(id) from a left join b on a.id=b.aid 

          DISTINCT查詢結(jié)果是 第一個表唯一的數(shù)據(jù) 重復(fù)的結(jié)果沒顯示出來

          SELECT
           DISTINCT(a.id), a.*,
           b.type 
          FROM
           table1 a
           LEFT JOIN table2 b ON a.sponsor_id = b.sponsor_id 
          WHERE
           b.type = 1 
           AND a.sponsor_id = 10;


          SELECT
           DISTINCT a.*,
           b.type 
          FROM
           table1 a
           LEFT JOIN table2 b ON a.sponsor_id = b.sponsor_id 
          WHERE
           b.type = 1 
           AND a.sponsor_id = 10;

          2 GROUP BY

          select * from a left join(select id from b group by idas b on a.id=b.aid

          拿出b表的一條數(shù)據(jù)關(guān)聯(lián) 使A表與B表所顯示的記錄數(shù)為 1:1對應(yīng)關(guān)系。

          SELECT 
           a.*,
           b.type 
          FROM
           table1 a
           LEFT JOIN ( SELECT * FROM table2 GROUP BY sponsor_id ) AS b ON a.sponsor_id = b.sponsor_id 
          WHERE
           b.type = 1 
           AND a.sponsor_id = 10;

          3 max取唯一

          select * from a left join (select max(idfrom table group by idas b on a.id=b.aid 

          拿出b表的最后一條數(shù)據(jù)關(guān)聯(lián)

          SELECT
           a.*,
           b.type 
          FROM
           table1 a
           LEFT JOIN ( SELECT MAX( kid ), type, sponsor_id FROM table2 GROUP BY sponsor_id ) AS b ON a.sponsor_id = b.sponsor_id 
          WHERE
           b.type = 1 
           AND a.sponsor_id = 10;

          4 IN巧用

          SELECT
           a.* 
          FROM
           table1 a 
          WHERE
           a.sponsor_id IN ( SELECT sponsor_id FROM table2 WHERE type = 1 AND sponsor_id = 10 );


          SELECT
           a.*,
           1 
          FROM
           table1 a 
          WHERE
           a.sponsor_id IN ( SELECT sponsor_id FROM table2 WHERE type = 1 AND sponsor_id = 10 );

          相信對于熟悉SQL的人來說,LEFT JOIN非常簡單,采用的時候也很多,但是有個問題還是需要注意一下。假如一個主表M有多個從表的話A B C …..的話,并且每個表都有篩選條件,那么把篩選條件放到哪里,就得注意嘍。

          (搜索公眾號SQL數(shù)據(jù)庫開發(fā),回復(fù)“SQL”,送你一份SQL學(xué)習(xí)寶典

          比如有個主表M,卡號是主鍵。

          有個從表A,客戶號、聯(lián)系方式是聯(lián)合主鍵,其中聯(lián)系方式,1-座機(jī),2-手機(jī)號碼

          如果想要查詢所有卡號對應(yīng)的手機(jī)號碼兩個字段,很簡單,SQL語句如下:

          SELECT A.卡號,B.手機(jī)號碼
          FROM A
          LEFT JOIN B
            ON A.客戶號=B.客戶號
          WHERE B.聯(lián)系方式='2'

          相信很多人這樣寫,估計實際工作中也會看到這樣的語句,并不是說這么寫一定會錯誤,實際SQL表達(dá)的思想一定是要符合業(yè)務(wù)邏輯的。

          前面已經(jīng)說清楚,所有卡號對應(yīng)的手機(jī)號碼。所有卡號,所以首先肯定以A表作為主表,并且左關(guān)聯(lián)B表,這樣A表所有的卡號一定會顯示出來,但是如果B表的篩選條件放到最外層,這樣就相當(dāng)于將A表關(guān)聯(lián)B表又做了一遍篩選,結(jié)果就是

          就會篩選出來這么一條數(shù)據(jù),丟失了A表中其他的卡號。

          實際工作中表結(jié)構(gòu)肯定沒這么簡單,關(guān)聯(lián)的表也會很多,當(dāng)有很多條件時,最好這么寫

          SELECT A.卡號,B.手機(jī)號碼
          FROM A
          LEFT JOIN (
              SELECT * FROM B
              B.聯(lián)系方式='2'
              )B
            ON A.客戶號=B.客戶號

          這么寫的話,A表中的數(shù)據(jù)肯定會完全保留,又能與B表的匹配,不會丟失數(shù)據(jù)。

          PS:

          • 表結(jié)構(gòu)
          • Left Join
          • Right Join
          • Inner Join
          • 表的關(guān)聯(lián)修改和刪除
          • 笛卡爾積

          1、表結(jié)構(gòu)

          表A

          2、Left Join

          示例:2.1

          Select * From A left join B on A.aid = B.bid;

          left join是以A表的記錄為基礎(chǔ)的,A可以看成左表,B可以看成右表,left join是以左表為準(zhǔn)的。換句話說,左表A的記錄將會全部表示出來,而右表B只會顯示符合搜索條件的記錄(例子中為: A.aid = B.bid),B表記錄不足的地方均為NULL.

          • A表所有記錄都會顯示,A表中沒有被匹配的行(如aid=5、6的行)相應(yīng)內(nèi)容則為NULL。
          • 返回的記錄數(shù)一定大于A表的記錄數(shù),如A表中aid=7行被B表匹配了3次(因為B表有三行bid=7)。

          注意:在Access中A.aid、B.bid不能縮寫成aid、bid,否則會提示“不支持鏈接表達(dá)式”,這一點不同于Where查詢。

          3、Right Join

          示例:3.1

          Select * From A right join B on A.aid = B.bid;

          仔細(xì)觀察一下,就會發(fā)現(xiàn),和left join的結(jié)果剛好相反,這次是以右表(B)為基礎(chǔ)的,A表不足的地方用NULL填充。

          4、Inner Join

          示例:4.1

          Select * From A inner join B on A.aid = B.bid;

          這里只顯示出了 A.aid = B.bid的記錄.這說明inner join并不以誰為基礎(chǔ),它只顯示符合條件的記錄。

          inner join 等同于Where查詢?nèi)纾?/p>

          Select * From A, B Where A.aid = B.bid

          5、表的關(guān)聯(lián)修改和刪除

          5.1修改

          示例:5.1.1

          update A left join B on A.aid = B.bid
          set A.aname = B.bname

          上述SQL實際操作的表為"Select * From A left join B on A.aid = B.bid",因此Access會提示更新13條記錄(Select查詢出的記錄就是13條)。對比“示例:2.1”返回的結(jié)果,分析update后的A表:

          • aid=5、6的記錄,被更新為NULL
          • aid=7的記錄,被更新了3次,依次是“b1997-1”、“b1997-2”、“b1997-3”,因此其結(jié)果為最后一次更新“b1997-3”

          對于上述SQL同樣可以將“A.aname = B.bname”改成“B.bname = A.aname”,執(zhí)行后B表將會被修改,但是執(zhí)行后B表會增加三行“0, a2005-1;0, a2005-2;0, a2006”,這也不難理解,因為Left Join執(zhí)行后,B表會出現(xiàn)三行空值。

          示例:5.1.2

          Where條件查詢在上面的SQL中同樣可以使用,其作用的表也是Select查詢出的關(guān)聯(lián)表。如下SQL

          update A left join B on A.aid = B.bid
          set A.aname = B.bname
          where A.aid <> 5

          執(zhí)行后A表的結(jié)果:

          對比第一次update可以發(fā)現(xiàn),aid=5的并沒有被更新。

          這里只講述left join,因為right join 和 inner join的處理過程等同于left join。另外Access中update語句中不能含有From關(guān)鍵字,這一點不同于其他數(shù)據(jù)庫。

          5.2刪除

          在Access中是不可以通過Left Join、Right Join、Inner Join來刪除某張表的記錄

          示例:5.2.2

          Delete From A inner join B on A.aid = B.bid
          where B.bname = "b1991"

          上述SQL的本意是刪除A表中aid=1的記錄,但執(zhí)行后表A和表B均未發(fā)生任何變化。若想實現(xiàn)此目的,下述SQL可以實現(xiàn)

          Delete From A
          Where A.aid In (Select bid From B Where B.bname="b1991")

          6、笛卡爾積

          如果A表有20條記錄,B表有30條記錄,則二者關(guān)聯(lián)后的笛卡爾積工20*30=600條記實錄。也就是說A表中的每條記錄都會于B表的所有記錄關(guān)聯(lián)一次,三種關(guān)聯(lián)方式實際上就是對“笛卡爾積”的處理方式不同。


          最后給大家分享我寫的SQL兩件套:《SQL基礎(chǔ)知識第二版》《SQL高級知識第二版》的PDF電子版。里面有各個語法的解釋、大量的實例講解和批注等等,非常通俗易懂,方便大家跟著一起來實操。

          有需要的讀者可以下載學(xué)習(xí),在下面的公眾號「數(shù)據(jù)前線」(非本號)后臺回復(fù)關(guān)鍵字:SQL,就行
          數(shù)據(jù)前線

          后臺回復(fù)關(guān)鍵字:1024,獲取一份精心整理的技術(shù)干貨
          后臺回復(fù)關(guān)鍵字:進(jìn)群,帶你進(jìn)入高手如云的交流群。

          推薦閱讀
          瀏覽 23
          點贊
          評論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報
          評論
          圖片
          表情
          推薦
          點贊
          評論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  TS人妖系列自慰 | 精品欧美视频 | AV电影亚洲 | 国产足交在线播放 | 丁香婷婷网 |