如题,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
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
靠人终究不靠己呀。。。终于搞定鸟。。。
这三个字段的关系真是的1-1-1么。
再查查,是不是Left join里的条件少写了个。。
主表与字表的关系都是一对多
你的这个查询就应该是存在多条记录才对。
一对多的关系在建立关联查询的时候,不出现一对多就有问题了。
当你查询到22编号的时候,你只要15的还是16的?当你查询到22下的15或16后,你只要10还是11?这个你都要明确。
如果明确了,倒是可以只查询一条。参考:
问题是我都要的。。。left join 本身是正常的,只是我这的需求不一样。。。
问题是我都要的。。。left join 本身是正常的,只是我这的需求不一样。。。
不过还是谢谢了
@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
@笨笨蜗牛: 谢谢,临时表我也用过了,而且我还有关联查询很多表,虽然left join 本身没有重复,对于我来说却重复了大量的数据呀。。。而且您这样查询一来每个主id对应的子记录就只有一条了。
@vistang: 我后面给你的SQL语句解决了重复的问题,不过,用的是max,你可以考虑用min或别的运算,如条件运算,如:
max (case MI_PaymentId when then ... else then end)
@笨笨蜗牛: 貌似根本就不能用join 查询。。
@vistang: 你的数据库、业务本身设计有问题。要不不会有你这样的问题出现的。
@笨笨蜗牛: 是啊,现在桑心啊,里面的数据都很多了。。。
既然主表和字表的关系式一对多,楼主不想要重复数据,那就根据子表查找主表不就好了。也可以根据图片上的结果去重复数据就行了,楼主首先要明确需要什么样的数据,哪个字段可以重复,哪个字段不可以重复。
thanks,关键我要这样关联起来查询很多表呀。。
left join 一对多 肯定会有重复的