I'd consider backup/restore of a mix of full and differential backups from prod to dev.
Then synch between this restored copy to your actual dev databases
SQL Server 2008 R2+ supports backup compression in Standard Edition (In SQL Server 2008 it was Enterprise Edition only) which makes this easier.
Reasons:
- You test your backup integrity and restore capability
- You can reset your dev database easily if some code monkey bollixes it
- You can compare "before" and "after" DDL, performance etc
- You can snapshot the restored database as needed to roll this back if you make changes
I've used this before and will use it again for these reasons
I suggested this in my answer to The smallest backup possible ... with SQL Server
I can't answer your question as to the absolutely best way. But I can offer a different way of solving the problem, which may or may not be better. It has a reasonably flat execution plan, and I think it will perform well. (I'm eager to know so share the results!)
I apologize for using my own syntax style instead of yours--it helps query wizardry come to me when everything lines up in its usual place.
The query is available in a SqlFiddle. I threw in an overlap for EmpID 1 just to be sure I had that covered. If you eventually find that overlaps cannot occur in presence data, then you can remove the final query and the Dense_Rank
calculations.
WITH Points AS (
SELECT DISTINCT
T.EmpID,
P.TimePoint
FROM
(
SELECT * FROM dbo.WorkTime
UNION SELECT * FROM dbo.BreakTime
UNION SELECT * FROM dbo.Absence
) T
CROSS APPLY (VALUES (StartTime), (EndTime)) P (TimePoint)
), Groups AS (
SELECT
P.EmpID,
P.TimePoint,
Grp =
Row_Number()
OVER (PARTITION BY P.EmpID ORDER BY P.TimePoint, X.Which) / 2
FROM
Points P
CROSS JOIN (VALUES (1), (2)) X (Which)
), Ranges AS (
SELECT
G.EmpID,
StartTime = Min(G.TimePoint),
EndTime = Max(G.TimePoint)
FROM Groups G
GROUP BY
G.EmpID,
G.Grp
HAVING Count(*) = 2
), Presences AS (
SELECT
R.*,
P.Present,
Grp =
Dense_Rank() OVER (PARTITION BY R.EmpID ORDER BY R.StartTime)
- Dense_Rank() OVER (PARTITION BY R.EmpID, P.Present ORDER BY R.StartTime)
FROM
Ranges R
CROSS APPLY (
SELECT
CASE WHEN EXISTS (
SELECT *
FROM dbo.WorkTime W
WHERE
R.EmpID = W.EmpID
AND R.StartTime < W.EndTime
AND W.StartTime < R.EndTime
) AND NOT EXISTS (
SELECT *
FROM dbo.BreakTime B
WHERE
R.EmpID = B.EmpID
AND R.StartTime < B.EndTime
AND B.StartTime < R.EndTime
) AND NOT EXISTS (
SELECT *
FROM dbo.Absence A
WHERE
R.EmpID = A.EmpID
AND R.StartTime < A.EndTime
AND A.StartTime < R.EndTime
) THEN 1 ELSE 0 END
) P (Present)
)
SELECT
EmpID,
StartTime = Min(StartTime),
EndTime = Max(EndTime)
FROM Presences
WHERE Present = 1
GROUP BY
EmpID,
Grp
ORDER BY
EmpID,
StartTime;
Note: performance of this query would be improved you combined the three tables and added a column to indicate what kind of time it was: work, break, or absence.
And why all the CTEs, you ask? Because each one is forced by what I need to do to the data. There's an aggregate, or I need to put a WHERE condition on a windowing function or use it in a clause where windowing functions aren't allowed.
Now I'm going to go off and see if I can't think up another strategy for accomplishing this. :)
For amusement I include here a "diagram" I made to help solve the problem:
------------
-----------------
---------------
-----------
--- ------ ------ ------------
---- ---- --- -------
The three sets of dashes (separated by spaces) represent, in order: presence data, absence data, and the desired result.
Best Answer
SE-Data
datediff(minute, 0, CaptureTime)
gives you the number of minutes since1900-01-01T00:00:00
.dateadd(minute, 1+datediff(minute, 0, CaptureTime), 0)
adds the number of minutes since1900-01-01T00:00:00
to1900-01-01T00:00:00
ending up with a datetime with only minutes.The
1+
is there because you wanted the next minute.To do the same with a 5 minute interval you need to do some calculations. Divide the minutes with
5
and multiply with5
gives you the minutes rounded down to a 5 minute precision. This works because the result of an integer division in SQL Server is an integer.