/* in this table you can define your shifts */
CREATE TABLE Shifts (
Time_start char(8),
Time_end char(8),
Day_shift integer,
Shift_order integer
)
-- shift 1
INSERT INTO Shifts VALUES( '07:01:00', '17:00:00', 0, 1 )
-- shift 2
INSERT INTO Shifts VALUES( '17:01:00', '23:00:00', 0, 2 )
-- shift 3
INSERT INTO Shifts VALUES( '23:01:00', '07:00:00', 1, 3 ) -- 05:00:00 of next day, so Day_shift is 1
/* this is special table, it contains only numbers from 0 to 365+ ( enough for one year ) */
CREATE TABLE Numbers ( Number integer )
/***************************************************************************/
/* just only for populating table Numbers, this needs to be done only once */
INSERT INTO Numbers VALUES( 0 )
INSERT INTO Numbers VALUES( 1 )
INSERT INTO Numbers VALUES( 2 )
INSERT INTO Numbers VALUES( 3 )
INSERT INTO Numbers VALUES( 4 )
INSERT INTO Numbers VALUES( 5 )
INSERT INTO Numbers
SELECT Numbers.Number + cnt.value
FROM Numbers
CROSS JOIN ( SELECT COUNT(*) AS value FROM Numbers ) AS cnt
INSERT INTO Numbers
SELECT Numbers.Number + cnt.value
FROM Numbers
CROSS JOIN ( SELECT COUNT(*) AS value FROM Numbers ) AS cnt
INSERT INTO Numbers
SELECT Numbers.Number + cnt.value
FROM Numbers
CROSS JOIN ( SELECT COUNT(*) AS value FROM Numbers ) AS cnt
INSERT INTO Numbers
SELECT Numbers.Number + cnt.value
FROM Numbers
CROSS JOIN ( SELECT COUNT(*) AS value FROM Numbers ) AS cnt
INSERT INTO Numbers
SELECT Numbers.Number + cnt.value
FROM Numbers
CROSS JOIN ( SELECT COUNT(*) AS value FROM Numbers ) AS cnt
INSERT INTO Numbers
SELECT Numbers.Number + cnt.value
FROM Numbers
CROSS JOIN ( SELECT COUNT(*) AS value FROM Numbers ) AS cnt
/***************************************************************************/
/* this is my testing table, I make this commented because you should have one */
/*
CREATE TABLE Timeattendance_T( Time_in datetime,
Time_out datetime )
INSERT INTO Timeattendance_T VALUES (
'2005-07-13 08:00:00', '2005-07-13 18:00:00')
INSERT INTO Timeattendance_T VALUES (
'2005-07-14 08:00:00', '2005-07-14 20:00:00')
INSERT INTO Timeattendance_T VALUES (
'2005-07-15 08:00:00', '2005-07-15 17:00:00')
INSERT INTO Timeattendance_T VALUES (
'2005-07-16 08:00:00', '2005-07-16 19:00:00')
INSERT INTO Timeattendance_T VALUES (
'2005-07-17 08:00:00', '2005-07-17 17:00:00')
INSERT INTO Timeattendance_T VALUES (
'2005-07-20 08:00:00', '2005-07-20 17:00:00')
INSERT INTO Timeattendance_T VALUES (
'2005-07-21 08:00:00', '2005-07-21 17:00:00')
INSERT INTO Timeattendance_T VALUES (
'2005-07-22 08:00:00', '2005-07-22 19:00:00')
INSERT INTO Timeattendance_T VALUES (
'2005-07-23 08:00:00', '2005-07-23 21:00:00')
-- that one you was talking about in previous posts
INSERT INTO Timeattendance_T VALUES (
'2005-07-25 10:00:00', '2005-07-25 23:00:00')
-- some special workers :-)
INSERT INTO Timeattendance_T VALUES (
'2005-07-26 22:30:00', '2005-07-27 07:50:00')
INSERT INTO Timeattendance_T VALUES (
'2005-07-27 08:00:00', '2005-07-28 06:00:00')
*/
/* and this statement should give you results you are want */
SELECT
Timeattendance_T.Time_in,
Timeattendance_T.Time_out,
SUM( CASE WHEN Shifts.Shift_Order = 1
THEN DATEDIFF( minute,
CASE WHEN Time_in > CONVERT( char(10), DATEADD( day, Numbers.Number, Date_range.Range_start ), 21 ) + ' ' + Shifts.Time_start THEN Time_in ELSE CONVERT( char(10), DATEADD( day, Numbers.Number, Date_range.Range_start ), 21 ) + ' ' + Shifts.Time_start END,
CASE WHEN Time_out < CONVERT( char(10), DATEADD( day, Numbers.Number + Shifts.Day_shift, Date_range.Range_start ), 21 ) + ' ' + Shifts.Time_end THEN Time_out ELSE CONVERT( char(10), DATEADD( day, Numbers.Number + Shifts.Day_shift, Date_range.Range_start ), 21 ) + ' ' + Shifts.Time_end END
)
ELSE 0 END
) AS Shift1,
SUM( CASE WHEN Shifts.Shift_Order = 2
THEN DATEDIFF( minute,
CASE WHEN Time_in > CONVERT( char(10), DATEADD( day, Numbers.Number, Date_range.Range_start ), 21 ) + ' ' + Shifts.Time_start THEN Time_in ELSE CONVERT( char(10), DATEADD( day, Numbers.Number, Date_range.Range_start ), 21 ) + ' ' + Shifts.Time_start END,
CASE WHEN Time_out < CONVERT( char(10), DATEADD( day, Numbers.Number + Shifts.Day_shift, Date_range.Range_start ), 21 ) + ' ' + Shifts.Time_end THEN Time_out ELSE CONVERT( char(10), DATEADD( day, Numbers.Number + Shifts.Day_shift, Date_range.Range_start ), 21 ) + ' ' + Shifts.Time_end END
)
ELSE 0 END
) AS Shift2,
SUM( CASE WHEN Shifts.Shift_Order = 3
THEN DATEDIFF( minute,
CASE WHEN Time_in > CONVERT( char(10), DATEADD( day, Numbers.Number, Date_range.Range_start ), 21 ) + ' ' + Shifts.Time_start THEN Time_in ELSE CONVERT( char(10), DATEADD( day, Numbers.Number, Date_range.Range_start ), 21 ) + ' ' + Shifts.Time_start END,
CASE WHEN Time_out < CONVERT( char(10), DATEADD( day, Numbers.Number + Shifts.Day_shift, Date_range.Range_start ), 21 ) + ' ' + Shifts.Time_end THEN Time_out ELSE CONVERT( char(10), DATEADD( day, Numbers.Number + Shifts.Day_shift, Date_range.Range_start ), 21 ) + ' ' + Shifts.Time_end END
)
ELSE 0 END
) AS Shift3
FROM Timeattendance_T
CROSS JOIN Numbers
INNER JOIN ( SELECT CONVERT( char(10), MIN( Time_in ), 21 ) AS Range_start,
DATEDIFF( day, MIN( Time_in ), MAX( Time_out ) ) + 1 AS Number_of_Days
FROM Timeattendance_T
) AS Date_range ON Date_range.Number_of_Days > Numbers.Number
CROSS JOIN Shifts
WHERE CONVERT( char(10), DATEADD( day, Numbers.Number, Date_range.Range_start ), 21 ) + ' ' + Shifts.Time_start BETWEEN Time_in AND Time_out
OR
CONVERT( char(10), DATEADD( day, Numbers.Number + Shifts.Day_shift, Date_range.Range_start ), 21 ) + ' ' + Shifts.Time_end BETWEEN Time_in AND Time_out
OR
Time_in BETWEEN CONVERT( char(10), DATEADD( day, Numbers.Number, Date_range.Range_start ), 21 ) + ' ' + Shifts.Time_start AND CONVERT( char(10), DATEADD( day, Numbers.Number + Shifts.Day_shift, Date_range.Range_start ), 21 ) + ' ' + Shifts.Time_end
OR
Time_out BETWEEN CONVERT( char(10), DATEADD( day, Numbers.Number, Date_range.Range_start ), 21 ) + ' ' + Shifts.Time_start AND CONVERT( char(10), DATEADD( day, Numbers.Number + Shifts.Day_shift, Date_range.Range_start ), 21 ) + ' ' + Shifts.Time_end
GROUP BY
Timeattendance_T.Time_in,
Timeattendance_T.Time_out
ORDER BY
Timeattendance_T.Time_in,
Timeattendance_T.Time_out