5

誰かがこの問題のきちんとした解決策に出くわしたのではないかと思います。いくつかのテーブルからデータを選択しようとしています。レコードは行ごとに一致しています。私は基本的に完全な外部結合の後ですが、1つの決定的な違いがあります。あるテーブルで結合している列に特定の値を持つ4つの行があり、別のテーブルにこの値を持つ3つの行がある場合、最初の3つの結果のみを結合し、4番目の行はあるかのように動作させます。一致しませんでした。

これは、結果を比較するときにトランザクションが複数回カウントされないようにする調整レポートを作成するためです。少しのグループ化といくつかの集計関数を使用することでこの問題を回避できますが、これにより、保持したい詳細の一部が非表示になります。

以下は、私が求めているものの種類を示す例です。コメント内の無効/擬似コードは、これが機能していると私がどのように考えているかを示しています。

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

4

2 に答える 2

5

私が正しく理解していれば、これはあなたが求めているものかもしれません:

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
于 2012-06-06T15:24:33.310 に答える
1

行を使い切る最善の方法は、(ROW_NUMBER を使用して) 疑似行番号を追加し、それを結合に含めることです。

于 2012-06-06T15:21:48.743 に答える