left join 去除重復


select * from ecs_admin_user as u left join (select * from ecs_admin_user_xundian group by user_id) as x using(user_id) where user_id=571

  

select * FROM ecs_admin_user a LEFT JOIN (select distinct user_id from ecs_admin_user_xundian) b using(user_id) WHERE a.user_id = 571

 

 

 

 

 

建表:

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 );


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

卡號 客戶號
6223123456781001 1001
6223123456781002 1002
6223123456781003 1003
有個從表A,客戶號、聯系方式是聯合主鍵,其中聯系方式,1-座機,2-手機號碼

客戶號 聯系方式 聯系號碼
1001 1 010-78586
1001 2 18810123456
1002 1 010-837433
1003 1 010-837433
如果想要查詢所有卡號對應的手機號碼兩個字段,很簡單,SQL語句如下:

SELECT A.卡號,B.手機號碼
FROM A
LEFT JOIN B
ON A.客戶號=B.客戶號
WHERE B.聯系方式='2'
相信很多人這樣寫,估計實際工作中也會看到這樣的語句,並不是說這么寫一定會錯誤,實際SQL表達的思想一定是要符合業務邏輯的。
前面已經說清楚,所有卡號對應的手機號碼。所有卡號,所以首先肯定以A表作為主表,並且左關聯B表,這樣A表所有的卡號一定會顯示出來,但是如果B表的篩選條件放到最外層,這樣就相當於將A表關聯B表又做了一遍篩選,結果就是

卡號 手機號碼
6223123456781001 18810123456
就會篩選出來這么一條數據,丟失了A表中其他的卡號。
實際工作中表結構肯定沒這么簡單,關聯的表也會很多,當有很多條件時,最好這么寫

SELECT A.卡號,B.手機號碼
FROM A
LEFT JOIN (
SELECT * FROM B
B.聯系方式='2'
)B
ON A.客戶號=B.客戶號
這么寫的話,A表中的數據肯定會完全保留,又能與B表的匹配,不會丟失數據。

PS:

1、表結構
2、Left Join
3、Right Join
4、Inner Join
5、表的關聯修改和刪除
6、笛卡爾積
1、表結構
表A 表B

 

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
示例:3.1

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


仔細觀察一下,就會發現,和left join的結果剛好相反,這次是以右表(B)為基礎的,A表不足的地方用NULL填充。

4、Inner Join
示例:4.1

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、表的關聯修改和刪除
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”返回的結果,分析update后的A表:

aid=5、6的記錄,被更新為NULL
aid=7的記錄,被更新了3次,依次是“b1997-1”、“b1997-2”、“b1997-3”,因此其結果為最后一次更新“b1997-3”
對於上述SQL同樣可以將“A.aname = B.bname”改成“B.bname = A.aname”,執行后B表將會被修改,但是執行后B表會增加三行“0, a2005-1;0, a2005-2;0, a2006”,這也不難理解,因為Left Join執行后,B表會出現三行空值。

示例: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
執行后A表的結果:


對比第一次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")
6、笛卡爾積
如果A表有20條記錄,B表有30條記錄,則二者關聯后的笛卡爾積工20*30=600條記實錄。也就是說A表中的每條記錄都會於B表的所有記錄關聯一次,三種關聯方式實際上就是對“笛卡爾積”的處理方式不同
————————————————
原文鏈接:https://blog.csdn.net/ZYC88888/article/details/83002882


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM