Click here to monitor SSC
SQLServerCentral is supported by Red Gate Software Ltd.
 
Log in  ::  Register  ::  Not logged in
 
 
 
        
Home       Members    Calendar    Who's On


Add to briefcase

How to report period wise data ? Expand / Collapse
Author
Message
Posted Tuesday, March 05, 2013 5:16 AM
SSC Rookie

SSC RookieSSC RookieSSC RookieSSC RookieSSC RookieSSC RookieSSC RookieSSC Rookie

Group: General Forum Members
Last Login: Friday, March 22, 2013 6:04 AM
Points: 46, Visits: 205
Hi ,

I have a table which holds the employee details :

/*******************************************************************/

/****** Object: Table [dbo].[empleaves] Script Date: 05-03-2013 17:42:59 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE TABLE [dbo].[empleaves](
[empid] [int] NULL,
[leavedate] [date] NULL
) ON [PRIMARY]

GO
INSERT [dbo].[empleaves] ([empid], [leavedate]) VALUES (1, CAST(0xCE360B00 AS Date))
GO
INSERT [dbo].[empleaves] ([empid], [leavedate]) VALUES (1, CAST(0xD0360B00 AS Date))
GO
INSERT [dbo].[empleaves] ([empid], [leavedate]) VALUES (2, CAST(0xD0360B00 AS Date))
GO
INSERT [dbo].[empleaves] ([empid], [leavedate]) VALUES (2, CAST(0xBA360B00 AS Date))
GO
INSERT [dbo].[empleaves] ([empid], [leavedate]) VALUES (2, CAST(0xBB360B00 AS Date))
GO
INSERT [dbo].[empleaves] ([empid], [leavedate]) VALUES (2, CAST(0xBC360B00 AS Date))
GO
INSERT [dbo].[empleaves] ([empid], [leavedate]) VALUES (3, CAST(0xC9360B00 AS Date))
GO
/*******************************************************************/


I need a query which will report the leaves of employees as :

empid StartingDate EndingDate NoOfDays
1 28-02-2013 28-02-2013 1
1 02-03-2013 02-03-2013 1
2 02-03-2013 02-03-2013 1
2 08-02-2013 10-02-2013 3
3 23-02-2013 23-02-2013 1


How can I achieve this .?

Post #1426760
Posted Tuesday, March 05, 2013 5:43 PM


SSCrazy

SSCrazySSCrazySSCrazySSCrazySSCrazySSCrazySSCrazySSCrazy

Group: General Forum Members
Last Login: Yesterday @ 6:07 PM
Points: 2,340, Visits: 3,167
You can use the staggered row number approach to get this:

CREATE TABLE #empleaves(
[empid] [int] NULL,
[leavedate] [date] NULL
) ON [PRIMARY]

GO
INSERT #empleaves ([empid], [leavedate]) VALUES (1, CAST(0xCE360B00 AS Date))
INSERT #empleaves ([empid], [leavedate]) VALUES (1, CAST(0xD0360B00 AS Date))
INSERT #empleaves ([empid], [leavedate]) VALUES (2, CAST(0xD0360B00 AS Date))
INSERT #empleaves ([empid], [leavedate]) VALUES (2, CAST(0xBA360B00 AS Date))
INSERT #empleaves ([empid], [leavedate]) VALUES (2, CAST(0xBB360B00 AS Date))
INSERT #empleaves ([empid], [leavedate]) VALUES (2, CAST(0xBC360B00 AS Date))
INSERT #empleaves ([empid], [leavedate]) VALUES (3, CAST(0xC9360B00 AS Date))

;WITH GroupDates AS (
SELECT empid, leavedate
,rd=CAST(leavedate AS DATETIME)-ROW_NUMBER() OVER (PARTITION BY empid ORDER BY leavedate)
FROM #empleaves)
SELECT empid, StartingDate=MIN(leavedate), EndingDate=MAX(leavedate)
,NoOfDays=1+DATEDIFF(day, MIN(leavedate), MAX(leavedate))
FROM GroupDates
GROUP BY empid, rd
ORDER BY empid, StartingDate

DROP TABLE #empleaves


Jeff Moden doesn't call it that in his article, but here is where it is described: Group Islands of Contiguous Dates



No loops! No CURSORs! No RBAR! Hoo-uh!

INDEXing a poor-performing query is like putting sugar on cat food. Yeah, it probably tastes better but are you sure you want to eat it?

Need to UNPIVOT? Why not CROSS APPLY VALUES instead?
Since random numbers are too important to be left to chance, let's generate some!
Are you too recursively challenged?
Splitting strings based on patterns can be fast!
Post #1427094
Posted Tuesday, March 05, 2013 6:10 PM


SSCommitted

SSCommittedSSCommittedSSCommittedSSCommittedSSCommittedSSCommittedSSCommittedSSCommitted

Group: General Forum Members
Last Login: Yesterday @ 2:35 PM
Points: 1,561, Visits: 2,310
Well, Dwain, I was about to suggest the data should be stored with some sort of identifying element as to indicate whether or not the date indicates a leave or a return, lest one be tempted to do something like this...
WITH Dates AS
(
SELECT
empid,
leavedate,
Rownum = CASE WHEN ROW_NUMBER() OVER (PARTITION BY empid ORDER BY leavedate) % 2 = 0
THEN 2
ELSE 1
END,
instance = ((ROW_NUMBER() OVER (PARTITION BY empid ORDER BY leavedate) -
CASE WHEN ROW_NUMBER() OVER (PARTITION BY empid ORDER BY leavedate) % 2 = 0
THEN 2
ELSE 1
END)/2) + 1
FROM empleaves
), Dates2 AS
(
SELECT
empid,
instance,
LeaveDate = MAX(CASE WHEN Rownum = 1 THEN leavedate ELSE NULL END),
ReturnDate = MAX(CASE WHEN Rownum = 2 THEN leavedate ELSE NULL END)
FROM Dates
GROUP BY empid, instance
)
SELECT
*,
NoOfDays = DATEDIFF(d,leavedate,returndate)
FROM Dates2
ORDER BY empid, instance

However, it looks like I am getting rustier the longer I dwell in the mainframe world. Anyhow, I still think a data structure like this still leaves a whole lot of room for error. For example, what would happen if someone (or some process) did not enter a return date, so what is really two consecutive dates appear to be a leave and return date, but in reality are two leave dates? Once again, thanks for the showing, me anyway, a new trick.


Greg
_________________________________________________________________________________________________
The glass is at one half capacity: nothing more, nothing less.
Post #1427104
Posted Tuesday, March 05, 2013 6:13 PM


SSCommitted

SSCommittedSSCommittedSSCommittedSSCommittedSSCommittedSSCommittedSSCommittedSSCommitted

Group: General Forum Members
Last Login: Yesterday @ 2:35 PM
Points: 1,561, Visits: 2,310
dwain.c (3/5/2013)
Jeff Moden doesn't call it that in his article, but here is where it is described: Group Islands of Contiguous Dates


Ah yes, I do remember reading that now. Thank you Jeff.


Greg
_________________________________________________________________________________________________
The glass is at one half capacity: nothing more, nothing less.
Post #1427105
Posted Tuesday, March 05, 2013 6:30 PM


SSCrazy

SSCrazySSCrazySSCrazySSCrazySSCrazySSCrazySSCrazySSCrazy

Group: General Forum Members
Last Login: Yesterday @ 6:07 PM
Points: 2,340, Visits: 3,167
Greg Snidow (3/5/2013)
Well, Dwain, I was about to suggest the data should be stored with some sort of identifying element as to indicate whether or not the date indicates a leave or a return, lest one be tempted to do something like this...
WITH Dates AS
(
SELECT
empid,
leavedate,
Rownum = CASE WHEN ROW_NUMBER() OVER (PARTITION BY empid ORDER BY leavedate) % 2 = 0
THEN 2
ELSE 1
END,
instance = ((ROW_NUMBER() OVER (PARTITION BY empid ORDER BY leavedate) -
CASE WHEN ROW_NUMBER() OVER (PARTITION BY empid ORDER BY leavedate) % 2 = 0
THEN 2
ELSE 1
END)/2) + 1
FROM empleaves
), Dates2 AS
(
SELECT
empid,
instance,
LeaveDate = MAX(CASE WHEN Rownum = 1 THEN leavedate ELSE NULL END),
ReturnDate = MAX(CASE WHEN Rownum = 2 THEN leavedate ELSE NULL END)
FROM Dates
GROUP BY empid, instance
)
SELECT
*,
NoOfDays = DATEDIFF(d,leavedate,returndate)
FROM Dates2
ORDER BY empid, instance

However, it looks like I am getting rustier the longer I dwell in the mainframe world. Anyhow, I still think a data structure like this still leaves a whole lot of room for error. For example, what would happen if someone (or some process) did not enter a return date, so what is really two consecutive dates appear to be a leave and return date, but in reality are two leave dates? Once again, thanks for the showing, me anyway, a new trick.


You are welcome Greg. I just love that trick and found that it has other applications than just contiguous dates (for example take a look at the 4th link in my signature on pattern splitting).

I agree there are dangers in this data structure. One for example is that mine doesn't cover is if the leave is contiguous over periods where the employee has the day off (e.g., Saturdays and Sundays).



No loops! No CURSORs! No RBAR! Hoo-uh!

INDEXing a poor-performing query is like putting sugar on cat food. Yeah, it probably tastes better but are you sure you want to eat it?

Need to UNPIVOT? Why not CROSS APPLY VALUES instead?
Since random numbers are too important to be left to chance, let's generate some!
Are you too recursively challenged?
Splitting strings based on patterns can be fast!
Post #1427111
Posted Tuesday, March 05, 2013 9:45 PM
SSC Rookie

SSC RookieSSC RookieSSC RookieSSC RookieSSC RookieSSC RookieSSC RookieSSC Rookie

Group: General Forum Members
Last Login: Friday, March 22, 2013 6:04 AM
Points: 46, Visits: 205
Thanks a lot dwain.. It's working :)
Post #1427161
Posted Tuesday, March 05, 2013 9:47 PM
SSC Rookie

SSC RookieSSC RookieSSC RookieSSC RookieSSC RookieSSC RookieSSC RookieSSC Rookie

Group: General Forum Members
Last Login: Friday, March 22, 2013 6:04 AM
Points: 46, Visits: 205
Thanks a ton everyone.. I am jumping to the pool. Lot of things pending.. Thanks again... :)
Post #1427162
Posted Tuesday, March 05, 2013 11:57 PM
SSC Rookie

SSC RookieSSC RookieSSC RookieSSC RookieSSC RookieSSC RookieSSC RookieSSC Rookie

Group: General Forum Members
Last Login: Friday, March 22, 2013 6:04 AM
Points: 46, Visits: 205
You are right. This structure is risky. But fortunately , this lies in the old DB from which we are migrating data to a new beautiful one :)
Post #1427189
« Prev Topic | Next Topic »

Add to briefcase

Permissions Expand / Collapse