Okay everyone,
Apologies in advance for the length. This one's actually kind of fun, though.
I wrote up a SQL script that I was semi-proud of yesterday because I thought it was quite clever. Turns out it gets ruined by performance issues, and I can't even test it because of that, so it may not even be doing what I think sigh.
This problem is best explained with an example:
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
With this table I need to: 1. Starting with the first, update the row with the data following it if the values in Column A match, 2. delete the second row after the update if there was a match, and 3. move on to the next row if there was no match and rerun the same process.
If there's a match, the higher row updates based on the following:
Then I delete the lower row.
My example should result in the following:
Heart | K | 1/1/2013 | 4/1/2013
Spade | Multiple | 2/1/2013 | 3/1/2013
Club | 4 | 2/1/2013 | 3/1/2013
To do all this I created two table variables, inserted the same data into both, and then cycled through the second (@ScheduleB) looking for matches to update the row in the first table (@ScheduleA). I then deleted the row below the row in @A (because it's the same as B). Finally, when there wasn't a match, I moved to the next row in @A to start the process over. At least that's what the code's supposed to do -- see below.
The problem is performance is TERRIBLE. I've considered using a Cursor, but don't know if the performance would help there.
Any suggestions?
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
EDIT: To clarify, column B is NOT an integer column, I was simply using this as an example because cards are pretty easily understood. I've since updated the column to include K's.
Based on your requirements I think a solution like this would work:
SELECT
[column a],
CASE WHEN MAX([column b]) <> MIN([column b]) THEN 'multiple' ELSE CAST(MAX([column b]) AS NVARCHAR(10)) END,
MIN([column c]),
MAX([column d])
FROM Table
GROUP BY [column a]
EDIT: