首页 新闻 搜索 专区 学院

sql server 多个left join 之后数据重复的问题

3
悬赏园豆:60 [已解决问题] 解决于 2012-06-14 16:35

如题,sql 语句如下

select a.ExpenditureContractId,
b.MI_SettlementId,c.MI_PaymentId
from MI_ExpenditureContract a
left join MI_Settlement b on b.MI_ContractId= a.ExpenditureContractId
left join MI_Payment c on c.MI_ContractId= a.ExpenditureContractId

ExpenditureContractId 为主表编号,MI_SettlementId和MI_PaymentId分别为子表ID,现在关于一个主表编号 子表均有2条记录,希望不重复的查询出来,而在使用连续的左连接之后却出现了 子表之间的笛卡尔积,左连接虽然没问题,但是却不是我想要的结果,泪流满面呀。。。

 

问题补充:

附测试数据sql以及查询

CREATE TABLE TM(
    [MID] [int] IDENTITY(1,1) NOT NULL,
    [UserName] [nvarchar](20) NULL,
)
CREATE TABLE TA(
    [AID] [int] IDENTITY(1,1) NOT NULL,
    [MID] [int] NOT NULL,
    [ADATE] [nvarchar](20) NULL,
)
CREATE TABLE TB(
    [BID] [int] IDENTITY(1,1) NOT NULL,
    [MID] [int] NOT NULL,
    [BDATE] [nvarchar](20) NULL,
)
insert into TM(UserName) values('wang');
insert into TM(UserName) values('zhang');
insert into TM(UserName) values('zhou');

insert into TA(MID,ADATE) values(1,'2012-06-08');
insert into TA(MID,ADATE) values(1,'2012-06-09');


insert into TB(MID,BDATE) values(1,'2099-06-08');
insert into TB(MID,BDATE) values(1,'2099-06-09');

 

 

select * from
tm a 
left join ta b on b.MID=a.MID
left join tb c on c.MID=a.MID
vistang的主页 vistang | 初学一级 | 园豆:69
提问于:2012-06-09 09:01
< >
分享
最佳答案
1
CREATE TABLE #temp2
(
 [MID] [int] ,
 [AID] [int] ,
 [ADATE] [nvarchar](20),
 [BID] [int] ,
 [BDATE] [nvarchar](20)
)
--------------------------------------------
 declare @tagint int -- first while repeat count
 declare @tmcount int --main table record count
 declare @tempMID int 
 -------------------------
 declare @taCount int 
 declare @taID int
 declare @tbCount int 
 declare @tbID int 
 declare @maxcount int
 ---------------------------
 declare @whilecount int
 -------------------------
 ---here is your new table constructor
 declare @taMid int
 declare @taDate nvarchar(20)
 declare @tbMid int
 declare @tbDate nvarchar(20)
 -----------------------------
 set @tagint =0
 select @tmcount =COUNT(MID) from TM  ---get total count 
set @tempMID =0
 while(@tagint<@tmcount)
   begin   
      select top 1 @tempMID =TM.MID from TM where MID >@tempMID
      set @taCount =0
      set @tbCount =0
      --select top 1 @tempMID =TM.MID from TM where MID not in(select top @tagint MID from TM order by TM.MID asc)
      select @taCount = count(distinct TA.AID) from TA where TA.MID =@tempMID   --获取a表中包含的合同数
      select @tbCount = count(distinct TB.BID) from TB where TB.MID=@tempMID  --获取b表中包含的合同数
      
      if(@taCount>@tbCount)begin set @maxcount =@taCount end --获取合同多的为循环数
      else begin set @maxcount=@tbCount end
      
      set @whilecount =0
      set @taID =0
      set @tbID =0
      while(@whilecount<@maxcount)
      begin  --start constructor new table data

      set @taDate =''
      set @tbDate=''
      select top 1 @taID=TA.AID,@taMid =TA.MID,@taDate =TA.ADATE from TA where TA.AID>@taID and TA.MID=@tempMID
      select top 1 @tbID=TB.BID,@tbMid =TB.MID,@tbDate =TB.BDATE from TB where TB.BID>@tbID and TB.MID=@tempMID
      insert into #temp2 (MID,AID,ADATE,BID,BDATE) values(@tempMID,@taID,@taDate,@tbID,@tbDate)
      set @whilecount =@whilecount +1
      end
      
     set @tagint =@tagint +1
    end
    select * from #temp2
drop table #temp2
      

靠人终究不靠己呀。。。终于搞定鸟。。。

vistang | 初学一级 |园豆:69 | 2012-06-11 08:54
其他回答(4)
0

这三个字段的关系真是的1-1-1么。

再查查,是不是Left join里的条件少写了个。。

雷池 | 园豆:202 (菜鸟二级) | 2012-06-09 09:09

主表与字表的关系都是一对多

支持(0) 反对(0) vistang | 园豆:69 (初学一级) | 2012-06-09 09:15
0

你的这个查询就应该是存在多条记录才对。

一对多的关系在建立关联查询的时候,不出现一对多就有问题了。

当你查询到22编号的时候,你只要15的还是16的?当你查询到22下的15或16后,你只要10还是11?这个你都要明确。

如果明确了,倒是可以只查询一条。参考:

请问该SQL是怎么执行的

收获园豆:50
无之无 | 园豆:5085 (大侠五级) | 2012-06-09 09:35

问题是我都要的。。。left join 本身是正常的,只是我这的需求不一样。。。

支持(0) 反对(0) vistang | 园豆:69 (初学一级) | 2012-06-09 09:41

问题是我都要的。。。left join 本身是正常的,只是我这的需求不一样。。。

不过还是谢谢了

支持(0) 反对(0) vistang | 园豆:69 (初学一级) | 2012-06-09 09:42

@vistang: 一对多的关系,LEFT JOIN后就是这样的结果。如果你要一条,可以用我给你的连接里的方案,来查询一条数据出来。

 

这个情况,用单条SQL语句实现起来有点麻烦,建议你还是使用临时表来实现,这样的性能会更好点。

 

select ExpenditureContractId, max(MI_SettlementId), max(MI_PaymentId)  from (select a.ExpenditureContractId,
b.MI_SettlementId,c.MI_PaymentId
from MI_ExpenditureContract a
left join MI_Settlement b on b.MI_ContractId= a.ExpenditureContractId
left join MI_Payment c on c.MI_ContractId= a.ExpenditureContractId) t group by ExpenditureContractId

 

支持(0) 反对(0) 无之无 | 园豆:5085 (大侠五级) | 2012-06-09 10:00

@笨笨蜗牛: 谢谢,临时表我也用过了,而且我还有关联查询很多表,虽然left join 本身没有重复,对于我来说却重复了大量的数据呀。。。而且您这样查询一来每个主id对应的子记录就只有一条了。

支持(0) 反对(0) vistang | 园豆:69 (初学一级) | 2012-06-09 10:05

@vistang: 我后面给你的SQL语句解决了重复的问题,不过,用的是max,你可以考虑用min或别的运算,如条件运算,如:

max (case MI_PaymentId when then  ... else then end)

支持(0) 反对(0) 无之无 | 园豆:5085 (大侠五级) | 2012-06-09 10:11

@笨笨蜗牛: 貌似根本就不能用join 查询。。

支持(0) 反对(0) vistang | 园豆:69 (初学一级) | 2012-06-09 10:33

@vistang: 你的数据库、业务本身设计有问题。要不不会有你这样的问题出现的。

支持(0) 反对(0) 无之无 | 园豆:5085 (大侠五级) | 2012-06-09 11:20

@笨笨蜗牛: 是啊,现在桑心啊,里面的数据都很多了。。。

支持(0) 反对(0) vistang | 园豆:69 (初学一级) | 2012-06-09 12:08
1

既然主表和字表的关系式一对多,楼主不想要重复数据,那就根据子表查找主表不就好了。也可以根据图片上的结果去重复数据就行了,楼主首先要明确需要什么样的数据,哪个字段可以重复,哪个字段不可以重复。

收获园豆:5
墨猦 | 园豆:668 (小虾三级) | 2012-06-09 10:00

thanks,关键我要这样关联起来查询很多表呀。。

支持(0) 反对(0) vistang | 园豆:69 (初学一级) | 2012-06-09 10:07
1

left join  一对多 肯定会有重复的

收获园豆:5
xu_happy_you | 园豆:222 (菜鸟二级) | 2012-06-09 18:33
清除回答草稿
   您需要登录以后才能回答,未注册用户请先注册