2017-08-31 5 views
0

まず、セットアップを説明しましょう。私たちは、私たちが見ているSQL Server 2012の上に2つのテーブルを持って次のようにすべてのアカウントのゲストの最小日

PL_Guest and PL_MergedGuests 

PL_Guest構造は次のとおりです。次のように

Create Table PL_Guest(
GuestID [int] IDENTITY(1,1) NOT NULL Primary Key, 
CreatedDate [date] NOT NULL) 

PL_MergedGuests構造は次のとおりです。

Create Table PL_MergedGuests(
MergeID [int] IDENTITY(1,1) NOT NULL Primary Key, 
VictimID [int] NOT NULL, 
SurvivorID [int] NOT NULL) 

だから、状況がされthis:

PL_Guestテーブルは、これまでに作成したすべてのゲストのレコードを保持していますrにはレコードが削除されています。 PL_MergedGuestsテーブルには、2つのアカウントをマージするときのvictimidとsurvivoridのリストが格納されています。たとえば、ある人が何らかの理由で複数のGuestidを割り当てられている場合、これを実行します。現在、マージが行われると、フロントラインの従業員は、その人が保持する複数のアカウントのうちのどれを選択するかは、通常、ゲストが手に入れているカードに基づいて行われ、ゲストの変更は少なくなります。ゲストがCreatedDate 1/1/2013でGuestID 5を、GuestID 10にCreatedDate 10/20/1を持つゲストがあった場合、 GuestID 5がGuestID 10にマージされ、次にGuestID 5がVictimになり、GuestID 10が生存者になるようにマージが行われました。レポートを実行すると、生存者のアカウントだけが表示されます。しかし、我々は各ゲストのために最も古いCreated Dateを見つけるよう求められています。したがって、上記の例では、GuestID 10を返すエントリが必要です。GuestID 10のゲストとして作成された日付1/1/2013には、2013年1月1日の古い作成日のGuestID 5もあります。

本当に難しい部分については、ゲストがマージされた可能性のある回数に制限はなく、これらのテーブルにはそれぞれ1億レコード以上が保持されます。私はこれが何らかのループを必要とすると思っていた(これは再帰的なコーディングと呼ばれるかもしれないが、私はそれは不確かだと思う)が、そのコードを書く方法は失われている。それが助けになるが現在のテーブルを変更することができない場合は、私は新しいテーブルを作成するためのアクセス権を持っています。

+0

あなたが言った:「我々は、レポートを実行すると、我々は唯一の生存者のアカウントを見て"あなたは生き残ったゲストを今どのように知っていますか? 'PL_Guest'テーブルにフラグがありますか?はいの場合は、それに応じて質問を編集してください。 –

+0

生存者アカウントは、VictimIDがnullのGuestID = VictimIDのPL_MergedGuestへのPL_Guestの左結合を実行すると見つかります。 –

答えて

1

"実際の"例がないため、いくつかの例を自分で定義し、いくつかのマージを維持しました。私は希望の "分作成日"を評価するために再帰的なcteを使用しました。私はこれがあなたのテーブル上で動作しますか速いか遅いかわからないが、少なくとも、それがさらなる発展のために使用可能な出発点を提供する必要があります

DECLARE @PL_Guest TABLE(
    GuestID INT NOT NULL, 
    CreatedDate [date] NOT NULL 
) 

DECLARE @PL_MergedGuests TABLE(
    MergeID INT NOT NULL, 
    VictimID [int] NOT NULL, 
    SurvivorID [int] NOT NULL 
) 


INSERT INTO @PL_Guest 
    VALUES (1, '2016-11-01'), (2, '2016-12-01'), (3, '2016-11-01'), (4, '2016-12-01'), (5, '2017-01-01'), (6, '2017-01-01'), (7, '2017-02-01'), (8, '2017-02-01'), (9, '2017-03-01'), (10, '2017-04-01'); 

INSERT INTO @PL_MergedGuests 
    VALUES (1, 3, 4), (2, 4, 6), (3, 9, 6), (4, 10, 2), (5, 8, 5); 

WITH cteRecursice AS(
    SELECT mg1.SurvivorID, mg1.VictimID, 1 AS lvl, mg1.SurvivorID AS LastSurvivor, pg1.CreatedDate AS LastSurvivorCreatedDate 
    FROM @PL_MergedGuests mg1 
    JOIN @PL_Guest pg1 ON pg1.GuestID = mg1.SurvivorID 
    UNION ALL 
    SELECT mg2.SurvivorID, mg2.VictimID, c.lvl + 1 AS lvl, c.LastSurvivor, c.LastSurvivorCreatedDate 
    FROM @PL_MergedGuests mg2 
    JOIN cteRecursice c ON mg2.SurvivorID = c.VictimID 
), 
cteGrouped AS(
    SELECT LastSurvivor, LastSurvivorCreatedDate, MIN(CreatedDate) AS MinCreatedDate 
    FROM cteRecursice 
    JOIN @PL_Guest AS pg ON pg.GuestID = VictimID 
    WHERE LastSurvivor NOT IN (SELECT VictimID FROM @PL_MergedGuests AS pmg) 
    GROUP BY LastSurvivor, LastSurvivorCreatedDate 
    UNION ALL 
    SELECT GuestID, CreatedDate, CreatedDate 
    FROM @PL_Guest pg 
    WHERE GuestID NOT IN (SELECT VictimID FROM @PL_MergedGuests UNION ALL SELECT SurvivorID FROM @PL_MergedGuests) 
) 
SELECT LastSurvivor, IIF(MinCreatedDate < LastSurvivorCreatedDate, MinCreatedDate, LastSurvivorCreatedDate) AS MinCreatedDate 
    FROM cteGrouped cg 
    ORDER BY LastSurvivor 
    OPTION (MAXRECURSION 0) 
+1

ありがとう、ありがとうございます。これは私の問題に答えました。私は今週末にテストラボでテストを行います。しかし、これに関係なく、私は実用的な答えを得ることができます。 –

+1

私はテストラボでこれをテストすることができました。私はプロダクションサーバーに移動することができました。このコードは1分ほどで実行されています。助けてくれてありがとう。 –

+0

うれしい私は助けることができます。 :-) – Tyron78

関連する問題