0

複数のサプライヤーの変更がある ID の有効開始日と有効終了日を返す結果セットを戻したいと考えています。これを行うために、ID、サプライヤーの ID、およびトランザクションが発生した日付を記録するトランザクション テーブルを見ています。IDがサプライヤーを切り替えた場合、古い関連付けを廃止し、新しい関連付けを記録したいと考えています。私の意図は、最新の切り替え日を開始有効日として、null を有効終了日として新しい行を挿入することです。イベントを完了するために、最新の切り替え日が入力された終了有効日で最後の前の行を更新したいと考えています。トランザクションがあるが、ID がサプライヤーを切り替えていない場合、行を無視したい。

私が持っているものは単一の ID で機能しますが、2 番目の ID を追加すると、順序/パーティションが機能しません。

テスト行を生成するスクリプトは次のとおりです。単一の ID で機能する SQL が示されています。

    -- Note: use this to emulate the known switched suppliers table

    create table #switched
    (lcard bigint);

    insert into #switched (lcard) values (700382)
    insert into #switched (lcard) values (832019)

    select * from #switched

    -- Note: this temp data represents a previously grouped/partitioned table
            --       prepped for this next phase of action

    create table #PartitionTest 
    (   FauxId int,
        lcard bigint,
        suppId int,
        switchDate datetime
    );


    INSERT INTO #PartitionTest (FauxId,lcard,suppId,switchDate) VALUES (1,700382,506,cast('Jun 23 2013 12:00AM' as datetime))
    INSERT INTO #PartitionTest (FauxId,lcard,suppId,switchDate) VALUES (2,700382,49401,cast('May 22 2013 12:00AM' as datetime))
    INSERT INTO #PartitionTest (FauxId,lcard,suppId,switchDate) VALUES (3,700382,49401,cast('May  4 2013 12:00AM' as datetime))
    INSERT INTO #PartitionTest (FauxId,lcard,suppId,switchDate) VALUES (4,700382,49401,cast('May  2 2013 12:00AM' as datetime))
    INSERT INTO #PartitionTest (FauxId,lcard,suppId,switchDate) VALUES (5,700382,49401,cast('Apr 26 2013 12:00AM' as datetime))
    INSERT INTO #PartitionTest (FauxId,lcard,suppId,switchDate) VALUES (6,700382,49401,cast('Mar 15 2013 12:00AM' as datetime))
    INSERT INTO #PartitionTest (FauxId,lcard,suppId,switchDate) VALUES (1,832019,27088,cast('Jun 18 2013 12:00AM' as datetime))
    INSERT INTO #PartitionTest (FauxId,lcard,suppId,switchDate) VALUES (2,832019,232,cast('May 24 2013 12:00AM' as datetime))
    INSERT INTO #PartitionTest (FauxId,lcard,suppId,switchDate) VALUES (3,832019,232,cast('May 23 2013 12:00AM' as datetime))
    INSERT INTO #PartitionTest (FauxId,lcard,suppId,switchDate) VALUES (4,832019,232,cast('May 22 2013 12:00AM' as datetime))
    INSERT INTO #PartitionTest (FauxId,lcard,suppId,switchDate) VALUES (5,832019,232,cast('May 21 2013 12:00AM' as datetime))
    INSERT INTO #PartitionTest (FauxId,lcard,suppId,switchDate) VALUES (6,832019,232,cast('May 17 2013 12:00AM' as datetime))
    INSERT INTO #PartitionTest (FauxId,lcard,suppId,switchDate) VALUES (7,832019,232,cast('May 16 2013 12:00AM' as datetime))

    -- Note: Order results by lcard, then order the supplier id by
        --       the transaction date found. FauxId is from the previous partitioning

    select * from #PartitionTest
     order by lcard,fauxId, suppId, switchDate

    -- This is the statement that is failing when attempting to utilize 
        -- the ids in #switched as the criterion processing sets of ids.

    ;with sifted
        as ( select *,
          row_number() over (ORDER BY switchDate) - row_number() over (PARTITION BY suppId ORDER BY switchDate) as G
        from #PartitionTest
        where lcard in
         (select lcard
            from #switched
          )
         -- // DEBUG TEST: specific card holder(s)
         -- NOTE: when both lcards are used, the beginEffDate/endEffDate goal fails
         -- and lcard in ('8320198','7003824')
         -- NOTE: this represents the intent
         and lcard in ('832019')
        ),
       refined as
         (select lcard,
                 suppId,
                MIN(switchDate) BeginEffDate,
                ROW_NUMBER() OVER (ORDER BY min(switchDate)) as OrgSplit
         from sifted
          group by lcard,suppId, G)
   select a.lcard,
          a.suppId,
          a.BeginEffDate,
          b.BeginEffDate as EndEffDate
    from refined a
          left join refined b
            on a.OrgSplit + 1 = b.OrgSplit
    order by a.lcard, a.suppId



    -- drop table #switched;
    -- drop table #PartitionTest;

================================================== ================

編集済み

望ましい結果は次のとおりです。

ここに画像の説明を入力

4

2 に答える 2

0

siftedCTEの行を次のように変更するだけで済みました。

      row_number() over (ORDER BY switchDate) - row_number() over (PARTITION BY lcard, suppId ORDER BY switchDate) as G

lcard,PARTITION BY に注記を追加。

ステートメント全体は次のようになります。

;with sifted
    as ( select *,
      row_number() over (ORDER BY switchDate) - row_number() over (PARTITION BY lcard, suppId ORDER BY switchDate) as G
    from #PartitionTest
    where lcard in
     (select lcard
        from #switched
      )
     -- // DEBUG TEST: specific card holder(s)
     -- NOTE: when both lcards are used, the beginEffDate/endEffDate goal fails
     -- and lcard in ('8320198','7003824')
     -- NOTE: this represents the intent
     and lcard in (832019,700382)
    ),
   refined as
     (select lcard,
             suppId,
            MIN(switchDate) BeginEffDate,
            ROW_NUMBER() OVER (ORDER BY min(switchDate)) as OrgSplit
     from sifted
      group by lcard,suppId, G)

a.lcard、a.suppId、a.BeginEffDate、b.BeginEffDate を EndEffDate として選択 a.OrgSplit + 1 = b.OrgSplit の a.lcard、a.suppId の順序で a.lcard、a.suppId による左結合の洗練された a 左結合

混同された lcard と suppId の組み合わせを見るとすぐに、どこに問題があるかがわかりました

于 2013-07-23T02:07:56.800 に答える