https://mp.weixin.qq.com/s/Wmx915VJ1omZH_qWMibM0w
CREATE TABLE `table1` ( `id` int(11) NOT NULL AUTO_INCREMENT, `name` varchar(60) DEFAULT NULL, `age` varchar(200) DEFAULT NULL, `sponsor_id` varchar(20) DEFAULT NULL COMMENT '業務發起人', `gmt_create_user` int(11) NOT NULL COMMENT '創建人id', `gmt_create` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '創建時間', `gmt_modified` datetime DEFAULT NULL COMMENT '修改時間', `gmt_modified_user` int(11) DEFAULT NULL COMMENT '修改人id', PRIMARY KEY (`id`) ) ENGINE=InnoDB AUTO_INCREMENT=12 DEFAULT CHARSET=utf8mb4 COMMENT='測試表1'; CREATE TABLE `table2` ( `kid` int(11) NOT NULL AUTO_INCREMENT, `name` varchar(60) DEFAULT NULL, `sponsor_id` varchar(20) DEFAULT NULL COMMENT '業務發起人', `type` int(11) NOT NULL COMMENT '創建人id', `gmt_create` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '創建時間', `gmt_modified` datetime DEFAULT NULL COMMENT '修改時間', `gmt_modified_user` int(11) DEFAULT NULL COMMENT '修改人id', PRIMARY KEY (`kid`) ) ENGINE=InnoDB AUTO_INCREMENT=12 DEFAULT CHARSET=utf8mb4 COMMENT='測試表2';
插入數據:
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', NULL, NULL); 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', NULL, NULL); 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', NULL, NULL); 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', NULL, NULL);
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', NULL, NULL); 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', NULL, NULL); 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', NULL, NULL); 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', NULL, NULL); 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', NULL, NULL); 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', NULL, NULL); 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', NULL, NULL); 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', NULL, NULL);
查詢異常:
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;
簡單說明問題出現的原因:
MySQL left join 語句格式為:A LEFT JOIN B ON 條件表達式
left join 是以A表為基礎,A表即左表,B表即右表。
左表(A)的記錄會全部顯示,而右表(B)只會顯示符合條件表達式的記錄,如果在右表(B)中沒有符合條件的記錄,則記錄不足的地方為NULL。
使用left join, A表與B表所顯示的記錄數為 1:1 或 1:0,A表的所有記錄都會顯示,B表只顯示符合條件的記錄。
但如果B表符合條件的記錄數大於1條,就會出現1:n的情況,這樣left join后的結果,記錄數會多於A表的記錄數。
所以解決辦法 都是從一個出發點出發,使A表與B表所顯示的記錄數為 1:1對應關系。
解決方法:
使用非唯一標識的字段做關聯
1 DISTINCT
select DISTINCT(id) from a left join b on a.id=b.aid DISTINCT
查詢結果是 第一個表唯一的數據 重復的結果沒顯示出來
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 id) as b on a.id=b.aid
拿出b表的一條數據關聯 使A表與B表所顯示的記錄數為 1:1對應關系。
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(id) from table group by id) as b on a.id=b.aid
拿出b表的最后一條數據關聯
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 );
PS:
- 表結構
- Left Join
- Right Join
- Inner Join
- 表的關聯修改和刪除
- 笛卡爾積
1、表結構
2、Left Join
示例:2.1
Select * From A left join B on A.aid = B.bid;
left join是以A表的記錄為基礎的,A可以看成左表,B可以看成右表,left join是以左表為准的。換句話說,左表A的記錄將會全部表示出來,而右表B只會顯示符合搜索條件的記錄(例子中為: A.aid = B.bid),B表記錄不足的地方均為NULL.
- A表所有記錄都會顯示,A表中沒有被匹配的行(如aid=5、6的行)相應內容則為NULL。
- 返回的記錄數一定大於A表的記錄數,如A表中aid=7行被B表匹配了3次(因為B表有三行bid=7)。
注意:在Access中A.aid、B.bid不能縮寫成aid、bid,否則會提示“不支持鏈接表達式”,這一點不同於Where查詢。
3、Right Join
Select * From A right join B on A.aid = B.bid;
4、Inner Join
Select * From A inner join B on A.aid = B.bid;
這里只顯示出了 A.aid = B.bid的記錄.這說明inner join並不以誰為基礎,它只顯示符合條件的記錄。
inner join 等同於Where查詢如:
Select * From A, B Where A.aid = B.bid
5、表的關聯修改和刪除
update A left join B on A.aid = B.bid
set A.aname = B.bname
示例:5.1.2
Where條件查詢在上面的SQL中同樣可以使用,其作用的表也是Select查詢出的關聯表。如下SQL
update A left join B on A.aid = B.bid set A.aname = B.bname where A.aid <> 5
對比第一次update可以發現,aid=5的並沒有被更新。
這里只講述left join,因為right join 和 inner join的處理過程等同於left join。另外Access中update語句中不能含有From關鍵字,這一點不同於其他數據庫。
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的記錄,但執行后表A和表B均未發生任何變化。若想實現此目的,下述SQL可以實現
Delete From A
Where A.aid In (Select bid From B Where B.bname="b1991")