left joinとinner joinの結果の和と全体の等しくない思考

2130 ワード

テスト環境はmysqlですが、実際にはデータベース環境とは関係なく論理的な問題です.
1、建設表及びテストデータ構造
drop tables if exists xxxxx_iqy0708;
create table xxxxx_iqy0708(ip varchar(100));
drop table if exists xxxxx_chusou0708;
create table xxxxx_chusou0708(appkey varchar(100), ip varchar(100), identify varchar(100));
insert into xxxxx_iqy0708
VALUES('xx1.xx2.xx3.xx4'),('xx2.xx2.xx3.xx4'),('xx3.xx2.xx3.xx4');
insert into xxxxx_chusou0708(appkey,ip,identify)
VALUES
('CSAndroid','xx1.xx2.xx3.xx4','id1'),
('CSAndroid','xx2.xx2.xx3.xx4','id2'),
('CSAndroid','xx5.xx2.xx3.xx4','id8'),
('CSAndroid','xx6.xx2.xx3.xx4','id3'),
('CSIos','xx1.xx2.xx3.xx4','id2'),
('CSIos','xx2.xx2.xx3.xx4','id1'),
('CSIos','xx3.xx2.xx3.xx4','id3'),
('CSIos','xx2.xx2.xx3.xx4','id3'),
('CSIos','xx5.xx2.xx3.xx4','id3');

2、クエリーデータ
2.1、ip関連で両者の差セットを取る
select appkey,count(distinct identify)
from xxxxx_chusou0708 a1
left join xxxxx_iqy0708 a2 on a1.ip=a2.ip
where a2.ip is null
group by appkey;

--注意:ip関連によれば、対応するidentifyはすでに関係されているかもしれませんが、関連されていない可能性があります.つまり1つのidentifyが複数のipに対応する
appkey	count(distinct identify)
CSAndroid	2
CSIos	1

2.2、ip関連で両者の交差を取る
select appkey,count(distinct identify)
from xxxxx_chusou0708 a1
inner join xxxxx_iqy0708 a2 on a1.ip=a2.ip
group by appkey;

--ip関連は、関連上のidentifyに対応しています.同様に、1つのidentifyが複数のipに対応する
appkey	count(distinct identify)
CSAndroid	2
CSIos	3

2.3、全体計算identifyデータ
select appkey, count(distinct identify)
from xxxxx_chusou0708
group by appkey;

--すべての重量を除いて、理論的には、これは2.1+2.3の和以下になります.
appkey	count(distinct identify)
CSAndroid	4
CSIos	3

3、説明
元のデータの表示:
select * from xxxxx_chusou0708;
select * from xxxxx_iqy0708;
厳格に関連する場合、2.3=2.1+2.2;しかし、本文で述べた状況は例外で、時には回りくどいので、よく考えないと分からないことがあります.