Please start any new threads on our new
site at https://forums.sqlteam.com. We've got lots of great SQL Server
experts to answer whatever question you can come up with.
Author |
Topic |
IanMoyes
Starting Member
2 Posts |
Posted - 2012-02-22 : 06:37:06
|
Apologies for the terrible subject heading - and I guess this might be a problem that has been solved before. I have a system used to view, edit and finally approve forms. Every time a form is edited, a new row is created in a SQL table, which has the formID, the datetime of the edit, and whether the form has been finally approved.Assume I've sorted this dataset by FormID and then ascending EditTime (so it's chronologically in order as you go down.)FormID EditTime FinallyApproved-----------------------------------1 [Some Datetime] NO1 [Some Datetime] YES *2 [Some Datetime] NO2 [Some Datetime] YES *2 [Some Datetime] YES3 [Some Datetime] YES3 [Some Datetime] NO3 [Some Datetime] YES *3 [Some Datetime] YESI want to know, for each FormID, the earliest EditTime where the form was finally approved - where FinallyApproved = YES. I've used a * to show the row I want to know in that sample set.Easy enough for forms 1 and 2. But in form 3, a mistake was made. Someone approved the form, changed their mind later, and only on the third edit was the form really finished. That's why I want the second ocurrance of YES for that particular form.So, I'd like to select the earliest YES value for each form that with no NO values occurring later. And that's where I'm stumped!If anyone's got some tips as to how to go about this, I'd be very grateful. Thanks everyone! |
|
Transact Charlie
Master Smack Fu Yak Hacker
3451 Posts |
Posted - 2012-02-22 : 07:35:40
|
you could try something like this?Performance isn't great though.IF OBJECT_ID('tempdb..#data') IS NOT NULL DROP TABLE #dataGOCREATE TABLE #data ( [FormID] INT , [EditTime] DATETIME , [FinallyApproved] BIT )INSERT #data ([FormID], [EditTime], [FinallyApproved])VALUES (1, '2012-01-01T00:01:00', 0) , (1, '2012-01-01T04:21:00', 1) -- YES , (2, '2012-01-02T04:00:00', 0) , (2, '2012-01-02T08:00:00', 1) -- YES , (2, '2012-01-02T12:00:00', 1) , (3, '2012-01-03T00:00:00', 1) , (3, '2012-01-03T01:00:00', 0) , (3, '2012-01-03T02:00:00', 1) -- YES , (3, '2012-01-03T03:00:00', 1) CREATE INDEX IX_FormID_EditTime_Approved ON #data ([FinallyApproved], [FormID], [EditTime])SELECT * FROM #dataSELECT [FormID] , MIN([EditTime])FROM ( SELECT [FormID] , [EditTime] FROM #data AS d WHERE [FinallyApproved] = 1 AND NOT EXISTS ( SELECT 1 FROM #data AS d2 WHERE d2.[FormID] = d.[FormID] AND d2.[FinallyApproved] = 0 AND d2.[EditTime] > d.[EditTime] ) ) AS sampGROUP BY samp.[FormID] Charlie===============================================================Msg 3903, Level 16, State 1, Line 1736The ROLLBACK TRANSACTION request has no corresponding BEGIN TRANSACTION |
 |
|
visakh16
Very Important crosS Applying yaK Herder
52326 Posts |
Posted - 2012-02-22 : 09:50:42
|
quote: Originally posted by IanMoyes Apologies for the terrible subject heading - and I guess this might be a problem that has been solved before. I have a system used to view, edit and finally approve forms. Every time a form is edited, a new row is created in a SQL table, which has the formID, the datetime of the edit, and whether the form has been finally approved.Assume I've sorted this dataset by FormID and then ascending EditTime (so it's chronologically in order as you go down.)FormID EditTime FinallyApproved-----------------------------------1 [Some Datetime] NO1 [Some Datetime] YES *2 [Some Datetime] NO2 [Some Datetime] YES *2 [Some Datetime] YES3 [Some Datetime] YES3 [Some Datetime] NO3 [Some Datetime] YES *3 [Some Datetime] YESI want to know, for each FormID, the earliest EditTime where the form was finally approved - where FinallyApproved = YES. I've used a * to show the row I want to know in that sample set.Easy enough for forms 1 and 2. But in form 3, a mistake was made. Someone approved the form, changed their mind later, and only on the third edit was the form really finished. That's why I want the second ocurrance of YES for that particular form.So, I'd like to select the earliest YES value for each form that with no NO values occurring later. And that's where I'm stumped!If anyone's got some tips as to how to go about this, I'd be very grateful. Thanks everyone!
SELECT t.FormID,MIN(t.EditTime) AS EarliestApprovedDateFROM table tOUTER APPLY (SELECT COUNT(*) AS cnt FROM table WHERE FormID = t.FormID AND FinallyApproved='No' AND editTime > t.EditTime)t1WHERE COALESCE(t1.cnt,0)=0AND t.FinallyApproved='Yes'GROUP BY t.FormID ------------------------------------------------------------------------------------------------------SQL Server MVPhttp://visakhm.blogspot.com/ |
 |
|
IanMoyes
Starting Member
2 Posts |
Posted - 2012-02-22 : 11:35:13
|
Thanks very much to the two of you for your really quick responses - I've got both methods to work correctly. I can follow Transact Charlie's script quite easily: the methodology is straightforward in the way it is laid out.I think we'd both accept that visakh16 has provided a very slick bit of code - as a relative newcomer to SQL, APPLY is a command I've yet to run into. That piece of code has certainly given me a good reason to check out some documentation and get a grasp on how I might solve similar problems in the future.Once again, thanks very much to both you. My new stored procedure is looking mighty fine.Ian |
 |
|
Transact Charlie
Master Smack Fu Yak Hacker
3451 Posts |
Posted - 2012-02-22 : 14:07:24
|
lol. That apply clause is an abomination. (though a cunning one)it functions in exactly the same way as the WHERE NOT EXISTS Clause.I have no clue which would be faster.Charlie===============================================================Msg 3903, Level 16, State 1, Line 1736The ROLLBACK TRANSACTION request has no corresponding BEGIN TRANSACTION |
 |
|
|
|
|
|
|