では皆さん、
長文をあらかじめお詫び申し上げます。これは実際にはちょっと楽しいです。
私は SQL スクリプトを作成しましたが、それは非常に賢いと思ったので、昨日は半ば誇りに思っていました。パフォーマンスの問題で台無しになることが判明し、そのためにテストすることさえできないので、ため息をつくと思うことさえしていない可能性があります。
この問題は、次の例で最もよく説明されています。
列 A | 列 B | C列 | D列
Heart | K | 2/1/2013 | 3/1/2013
Heart | K | 2/1/2013 | 3/1/2013
Heart | K | 1/1/2013 | 3/1/2013
Heart | K | 2/1/2013 | 4/1/2013
Spade | 4 | 2/1/2013 | 3/1/2013
Spade | 3 | 2/1/2013 | 3/1/2013
Club | 4 | 2/1/2013 | 3/1/2013
このテーブルでは、次のことを行う必要があります。1.最初の行から始めて、列 A の値が一致する場合は、それに続くデータで行を更新します。2.一致した場合は、更新後に 2 番目の行を削除します。3.次に進みます。一致しなかった場合は次の行に進み、同じプロセスを再実行します。
一致する場合は、以下に基づいて上位の行が更新されます。
- A列:なし
- 列 B: 両方の値が同じ場合は一方の値のまま、そうでない場合は「複数」と記入
- 列 C: 2 つの間の早い方の日付を保持し、
- 列 D: 2 つの間の後の日付を保持し、
次に、下の行を削除します。
私の例は次のようになります。
列 A | 列 B | C列 | D列
Heart | K | 1/1/2013 | 4/1/2013
Spade | Multiple | 2/1/2013 | 3/1/2013
Club | 4 | 2/1/2013 | 3/1/2013
これをすべて行うために、2 つのテーブル変数を作成し、両方に同じデータを挿入し、2 番目 (@ScheduleB) を循環して一致を探し、最初のテーブル (@ScheduleA) の行を更新します。次に、@A の行の下の行を削除しました (B と同じであるため)。最後に、一致するものがない場合、@A の次の行に移動してプロセスを最初からやり直しました。少なくとも、それがコードの本来の目的です。以下を参照してください。
問題は、パフォーマンスがひどいことです。Cursor の使用を検討しましたが、パフォーマンスが役立つかどうかはわかりません。
助言がありますか?
Declare @ScheduleA Table
(
RowNumber int,
Period nvarchar(MAX),
Program nvarchar(MAX),
ControlAccount Nchar(50),
WorkPackage Nchar(50),
CAM Nchar(50),
EVM Nchar(50),
Duration int,
BLStart datetime,
BLFinish datetime
)
Declare @ScheduleB Table
(
RowNumber int,
Period nvarchar(MAX),
Program nvarchar(MAX),
ControlAccount Nchar(50),
WorkPackage Nchar(50),
CAM Nchar(50),
EVM Nchar(50),
Duration int,
BLStart datetime,
BLFinish datetime
)
Insert INTO @ScheduleA
Select ROW_NUMBER() OVER(order by workpackage desc) as [Row], Period, Program,
ControlAccount, WorkPackage, CAM, EVM, Duration, BLStart, BLFinish
From ScheduleData
where program = @Program and period = @Period
Insert INTO @ScheduleB
Select ROW_NUMBER() OVER(order by workpackage desc) as [Row], Period, Program,
ControlAccount, WorkPackage, CAM, EVM, Duration, BLStart, BLFinish
From ScheduleData
where program = @Program and period = @Period
declare @i int = 1
declare @j int = 2
--Create a loop for the second variable that counts up to the last row of the B table
While @j < (select MAX(ROWNUMBER) + 1 from @ScheduleB)
Begin
--if the tables match by WorkPackage THEN
IF ((select WorkPackage from @ScheduleA where RowNumber = @i) =
(select workpackage from @ScheduleB where RowNumber = @j))
Begin
Update @ScheduleA
--Update the Schedule CAM, BLStart, BLFinish of the A table (if necessary)
set CAM =
Case
--Set values in @ScheduleA Column B based on logic
End,
BLStart =
Case
--Set values in @ScheduleA Column C based on logic
End,
BLFinish =
Case
--Set values in @ScheduleA Column D based on logic
End
Where RowNumber = @i
Delete from @ScheduleA
where RowNumber = @i + 1
set @j = @j + 1 --next row in B
End
ELSE
set @i = @i + 1
END
編集: 明確にするために、列 B は整数列ではありません。カードは非常に簡単に理解できるため、これを例として使用しただけです。それ以来、K を含めるようにコラムを更新しました。