我想知道是否有人找到解决这个问题的巧妙方法。我试图从几个表中选择数据,让记录逐行匹配。我基本上追求的是完整的外部连接,但有一个关键的区别。如果我在一个表中连接的列中有四行具有特定值,而另一个表中有三行具有该值,我只希望连接前三个结果,第四个结果就像有一直不匹配。
这样做的原因是创建一个对账报告,以确保在比较结果时不会多次计算交易。我可以通过使用一些分组和一些聚合函数来解决这个问题,但这隐藏了我想保留的一些细节。
下面是一个示例,展示了我想要的东西,注释中的无效/伪代码说明了我如何认为这是有效的:
declare @t1 table (id bigint identity(1,1) primary key clustered, foreignKeyId bigint, otherData nvarchar(10))
declare @t2 table (id bigint identity(1,1) primary key clustered, foreignKeyId bigint, moreData nvarchar(10))
insert @t1 select 1, '1.1.1'
union all select 1, '1.1.2'
union all select 1, '1.1.3'
union all select 3, '1.3.1'
union all select 3, '1.3.2'
union all select 3, '1.3.3'
union all select 4, '1.4.3'
insert @t2 select 1, '2.1.1'
union all select 1, '2.1.2'
union all select 1, '2.1.3'
union all select 2, '2.2.1'
union all select 3, '2.3.1'
union all select 3, '2.3.2'
union all select 5, '2.5.1'
union all select 5, '2.5.2'
--demo of the functionality i'm hoping to acheive
--
/*
select t1.id id1
, t2.id id2
, t1.foreignKeyId fk1
, t2.foreignKeyId fk2
, t1.otherData otherData
, t2.moreData moreData
from @t1 t1
full funky join @t2 t2
on t1.foreignKeyId = t2.foreignKeyId
order by t1.id, t2.id --we'd need an order by to ensure the match could be applied in a predictable manner
*/
--
declare @funkyjoin table (id1 bigint, id2 bigint, fk1 bigint, fk2 bigint, otherData nvarchar(10), moreData nvarchar(10))
declare @id1 bigint, @id2 bigint
insert @funkyjoin (id1, fk1, otherData)
select id, foreignKeyId, otherData from @t1
while exists(select 1 from @t2)
begin
select top 1 @id2 = id from @t2 order by id
set @id1 = null
select top 1 @id1 = id1
from @funkyjoin
where fk2 is null
and fk1 in (select foreignKeyId from @t2 where id = @id2)
if @id1 is null
begin
insert @funkyjoin (id2, fk2, moreData)
select id, foreignKeyId, moreData
from @t2
where id = @id2
end
else
begin
update @funkyjoin
set id2 = @id2
, fk2 = fk1 --since we're joining on this we can just match it
, moreData = (select moreData from @t2 where id = @id2)
where id1 = @id1
end
delete from @t2 where id = @id2 --since this is only an example let's not worry about keeping our source data
end
select *
from @funkyjoin
order by coalesce(id1, id2)
我之前为电子表格上发生这种情况编写了一个类似的解决方案:http://officemacros.codeplex.com/#WorksheetMergeMacro
如果我理解正确,这可能就是你想要的:
select *
from (
select *,
row_number() over (partition by foreignKeyId order by id) as n
from @t1
) t1
full outer join (
select *,
row_number() over (partition by foreignKeyId order by id) as n
from @t2
) t2 on t1.foreignKeyId = t2.foreignKeyId and t1.n = t2.n
用完行的最佳方法是添加伪行号(使用 ROW_NUMBER)并将其包含在联接中。
给出的答案就是所需要的。如果提供上下文有帮助,只需提及反答案即可。对于实现该行为的语法上更简洁的方法,但目前不支持,将是:
full outer apply (select top(1) * ...)