1

重複するクライアント レコードを 1 つのレコードにマージするクエリを作成しようとしています。現在、何を何にマッピングする必要があるかを知るために、マッピングテーブルを作成しています。

これを支援するために私が書いた2つの関数を次に示します

CREATE FUNCTION FindDuplicateClients ()
RETURNS TABLE AS RETURN 
(
    select distinct CLIENT_GUID 
    from CLIENTS c
    inner join
    (
        select FIRST_NAME, LAST_NAME, HOME_PHONE
        from CLIENTS
        group by FIRST_NAME, LAST_NAME, HOME_PHONE
        having COUNT(*) > 1
    ) t on c.FIRST_NAME = t.FIRST_NAME and c.LAST_NAME = t.LAST_NAME and c.HOME_PHONE = t.HOME_PHONE)
go

--Find other clients that map to this client
CREATE FUNCTION FindDuplicateClientsByClient (@Client uniqueidentifier)
RETURNS TABLE AS RETURN 
(
    select distinct CLIENT_GUID 
    from CLIENTS c
    inner join
    (
        select x.FIRST_NAME, x.LAST_NAME, x.HOME_PHONE
        from CLIENTS x
        inner join 
        (
            select FIRST_NAME, LAST_NAME, HOME_PHONE
            from CLIENTS
            where CLIENT_GUID = @Client
        ) y on x.FIRST_NAME = y.FIRST_NAME and x.LAST_NAME = y.LAST_NAME and x.HOME_PHONE = y.HOME_PHONE
        group by x.FIRST_NAME, x.LAST_NAME, x.HOME_PHONE
        having COUNT(*) > 1
    ) t on c.FIRST_NAME = t.FIRST_NAME and c.LAST_NAME = t.LAST_NAME and c.HOME_PHONE = t.HOME_PHONE
    where CLIENT_GUID <> @Client)
go

最初の関数CLIENT_GUIDは、2 つ以上のレコードを持つすべての を正常に返します。2 番目の関数は GUID を渡し、「共通情報」 (この場合は名、姓、および自宅の電話番号) を共有する他のすべての GUID を返します。

問題は、マッピング テーブルに記入することです。いくつかの重複を優先するために従わなければならないルールがいくつかあります。たとえば、トランザクションを持っている人は、CLIENT_GUID変更を加える必要はありませんが、他の GUID をマージすることができます (他の GUID にトランザクションがなかった場合)。

--Create Mapping table
select CLIENT_GUID, CAST(null as uniqueidentifier) as NEW_CLIENT_GUID
into #mapping
from FindDuplicateClients()

--Do not map people who have transactions
update #mapping
set NEW_CLIENT_GUID = CLIENT_GUID
where CLIENT_GUID in (select CLIENT_GUID from trnHistory)

今、ここで私が困っているところです。NEW_CLIENT_GUID前のクエリで設定した人のリストを取得し、FindDuplicateClientsByClientその GUID に対して実行し、カーソルを使用せずに関数に渡されたNEW_CLIENT_GUID結果を設定する方法がわかりません。NEW_CLIENT_GUID

これは、カーソルを使用して思いついた方法です

declare cur cursor LOCAL FAST_FORWARD for select NEW_CLIENT_GUID from #mapping where NEW_CLIENT_GUID is not null
declare @NEW_CLIENT_GUID uniqueidentifier

open cur
fetch next from cur into @NEW_CLIENT_GUID
while @@fetch_status = 0
begin
    update #mapping
    set NEW_CLIENT_GUID = @NEW_CLIENT_GUID
    where CLIENT_GUID in (select CLIENT_GUID from FindDuplicateClientsByClient(@NEW_CLIENT_GUID)) --Find duplicates to this record
        and NEW_CLIENT_GUID is null --Do not reassign values that are already set (ie: duplicates that have transactions)

    fetch next from cur into @NEW_CLIENT_GUID
end 

close cur
deallocate cur

私に#mappingは、値セットを持つ各結果を反復処理することは正しくないように思えます。これを行う正しい方法は何ですか?私は SQL Server 2008 R2 を使用していますが、SQL Server 2005 とも互換性があるとよいと思います。

4

1 に答える 1

0

2 日が経過しましたが、回答はありませんでした。必要なことに対して十分なパフォーマンスが得られたので、カーソル ソリューションに固執しました。

前のパスでマップされていない人を見つけるために 2 回目のループを実行する必要があったときは、別の方法を使用しましたが、これは前のカーソルとまったく同じように動作する while ループです。

declare @tmpGuid uniqueidentifier
select @tmpGuid = CLIENT_GUID from #mapping where NEW_CLIENT_GUID is null 
while @@ROWCOUNT > 0
begin   
  --Set the first unset guid to itself
  update #mapping
  set NEW_CLIENT_GUID = @tmpGuid
  where CLIENT_GUID = @tmpGuid

  --set all other duplicates to the guid we just used.
  update #mapping
  set NEW_CLIENT_GUID = @tmpGuid
  where CLIENT_GUID in (select CLIENT_GUID from FindDuplicateClientsByClient(@tmpGuid))
       and NEW_CLIENT_GUID is null

  --get next guid
  select @tmpGuid = CLIENT_GUID from #mapping where NEW_CLIENT_GUID is null 
end
set nocount off
go
于 2012-11-05T15:01:15.690 に答える