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 |
|
Bill_C
Constraint Violating Yak Guru
299 Posts |
Posted - 2008-12-02 : 02:19:28
|
| Can anyone help with the logic (sql) for this please?Task:-1. A period of dates (Sdate - Edate ) is entered into the system and have to be grouped together by personID. So what we have is basically 4 fields PersonID, Sdate (the start for a session) and Edate (the end of that particular session) and another id field T_ID which is used to identify the person that runs that session, as this field can be used to add up all sessions for that person.2. Problem:- These dates can sometimes overlap, as the person may be involved in more than 1 activity, so a Sdate may be 24/07/2008 with the Edate for that session as 27/07/2008, but within the system we find another entry for that same personID as Sdate = 26/07/2008, with Edate as 30/07/2008.3. Now the total session time for each person has to be calculated whether the sessions overlap or not (a new session may just start to run after the previous one finishes, therefore we have 2 start and end dates making one continuous session)All this has to be done in number of days per session, with a total for consecutive sessions (where they exist)(Hope I'm making sense here!).So what we have (diagramatically) is possibly:-row1. --PersonID 1---T_ID 1-Sdate Edate(12/05/2005) (16/05/2005)row2. --PersonID 1--T_ID 2- Sdate Edate (17/05/2005) (22/05/2005)row3. --PersonID 2--T_ID 1- Sdate Edate (18/05/2005) (24/05/2005)row4. --PersonID 2--T_ID 3- Sdate Edate (23/05/2005) (28/05/2005)(I have put the dates in for clarity)So as you can see, in record 2 the start date for the second session starts immediately after the end of session 1, so these dates for this personID are to be stated as continuous, so we can use the Sdate of the first part and the Edate of the second part to give us total number of days, but in records 3 & 4 there is an overlap, we still have to add the total number of days for these two periods (sessions) as they are for the same personID, so the must be linked and total days added up.Any help anyone?Thanks |
|
|
visakh16
Very Important crosS Applying yaK Herder
52326 Posts |
Posted - 2008-12-02 : 02:30:02
|
| so what should be your expected output for above dataset? |
 |
|
|
Bill_C
Constraint Violating Yak Guru
299 Posts |
Posted - 2008-12-02 : 02:45:39
|
| Days for each period and running session, much like you would get with using 'Datediff("d", Sdate,Edate)', so if there are two or more running (or overlapping) periods then the number of days for each period as one count, plus the total number of days for the whole lot for each person (which will differ if there are overlapping periods, so it just won't be a case of Sdate (of first period) to Edate (of last Period)) |
 |
|
|
visakh16
Very Important crosS Applying yaK Herder
52326 Posts |
|
|
Bill_C
Constraint Violating Yak Guru
299 Posts |
Posted - 2008-12-02 : 04:12:06
|
| What I need to do is(It may have to be done in a loop or something, but)A session is a number of periods of time, it could be 1 period with a start date and end date, or it could be a number of periods which run into one whole session.1. Get out all the periods for a person found in the table.2. Find out which of those periods are consecutive or overlapping. (e.g. where Sdate of period2 <= Edate of period1)so in this case all periods found would have to be sorted on date 'ASC'3. Work out the number of days (length) for each of those periods. (e.g. Datediff("d", Sdate,Edate)4. Add up all the days for consecutive or overlapping periods to give me a total number of days for that whole session of periods.5. Loop for all periods found?Something along the lines of:-IF EXISTS (SELECT * FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = 'periodlengths')BEGIN DROP TABLE periodlengthsENDGOCREATE TABLE periodlengths ([recno] int,[PersId] int,[periodlength] int,[periodno] int,)Declare @sessionlength int -- number of days elapsed in a periodDeclare @session_no int --counter to get the total periods for each session--get person Select PersonID from table1 a--get all sessions for each person Select PersonID,Sdate,Edate,T_ID from table1 b Where a.PersonID = b.PersonID Order by Sdate @session_no = 0 Select PersonID,Sdate,Edate,T_ID from table1 c Where c.PersonID = b.PersonID and c.Sdate <= b.Edate-- now work out length of each session @sessionlength = Datediff("d",b.Sdate,c.Edate)-- next save the value of @sessionlength into periodlengths table @session_no = @session_no + 1 insert into periodlengths c.PersonID, @sessionlength, @session_no-- now I would have to loop somehow to get the next period for this person? |
 |
|
|
visakh16
Very Important crosS Applying yaK Herder
52326 Posts |
Posted - 2008-12-02 : 04:45:26
|
| did you check the link i posted?Not much use giving query. post some data as per instructions in link if you need help. |
 |
|
|
Bill_C
Constraint Violating Yak Guru
299 Posts |
Posted - 2008-12-02 : 09:05:53
|
Here is some more code, hope this helps:-CREATE TABLE [Tbl1]( [Sdate] [varchar](20) NULL, [Edate] [Varchar](20) NULL, [PersonID] [int] NULL, [T_ID] [int] NULL)GO--delete tbl1 from tbl1INSERT INTO [Tbl1]([Sdate],[Edate],[PersonID],[T_ID])values ('17/06/2005','24/06/2005',123,234)INSERT INTO [Tbl1]([Sdate],[Edate],[PersonID],[T_ID])values ('17/06/2005','24/06/2005',122,232)INSERT INTO [Tbl1]([Sdate],[Edate],[PersonID],[T_ID])values ( '11/06/2005','27/06/2005',125,235 )INSERT INTO [Tbl1]([Sdate],[Edate],[PersonID],[T_ID])values ( '09/06/2005','24/06/2005',127,234 )INSERT INTO [Tbl1]([Sdate],[Edate],[PersonID],[T_ID])values ( '11/06/2005','24/06/2005',128,238 )INSERT INTO [Tbl1]([Sdate],[Edate],[PersonID],[T_ID])values ( '17/06/2006','27/06/2006',129,234 )INSERT INTO [Tbl1]([Sdate],[Edate],[PersonID],[T_ID])values ( '22/06/2006','24/06/2006',143,237 )INSERT INTO [Tbl1]([Sdate],[Edate],[PersonID],[T_ID])values ( '26/06/2005','29/06/2005',163,234 )INSERT INTO [Tbl1]([Sdate],[Edate],[PersonID],[T_ID])values ( '28/06/2005','03/07/2005',163,235 )INSERT INTO [Tbl1]([Sdate],[Edate],[PersonID],[T_ID])values ( '23/06/2005','28/06/2005',143,232 )INSERT INTO [Tbl1]([Sdate],[Edate],[PersonID],[T_ID])values ( '17/06/2005','24/06/2005',124,234 )INSERT INTO [Tbl1]([Sdate],[Edate],[PersonID],[T_ID])values ( '23/06/2005','30/06/2005',125,231 )INSERT INTO [Tbl1]([Sdate],[Edate],[PersonID],[T_ID])values ( '24/06/2005','29/06/2005',123,238) goDeclare @sessionlength int -- number of days elapsed in a periodDeclare @session_no int --counter to get the total periods for each sessionDeclare @pid int--get personSelect PersonID from Tbl1 --get all sessions for each person Select PersonID,Sdate,Edate,T_ID from Tbl1 b Where PersonID = b.PersonID Order by Sdate --set @pid = PersonID --@session_no = 0 Select PersonID,Sdate,Edate,T_ID from Tbl1 c Where c.PersonID = PersonID and c.Sdate <= Edate -- now work out length of each session set @sessionlength = Datediff("d",b.Sdate,c.Edate) -- next save the value of @sessionlength into periodlengths table --@session_no = @session_no + 1 --insert into periodlengths print @pid + ', ' + @sessionlength + ', ' + @session_no |
 |
|
|
Bill_C
Constraint Violating Yak Guru
299 Posts |
Posted - 2008-12-02 : 09:42:59
|
| Thinking more on it, would a CURSOR be a better method of extracting the data?Seeing as i need to loop through to get all periods for each personid to build up a total session time? |
 |
|
|
Bill_C
Constraint Violating Yak Guru
299 Posts |
Posted - 2008-12-03 : 03:13:07
|
Update:What I have so far by using a cursor is:-CREATE TABLE [Tbl1]( [Sdate] [varchar](20) NULL, [Edate] [Varchar](20) NULL, [PersonID] [int] NULL, [T_ID] [int] NULL)GOINSERT INTO [Tbl1]([Sdate],[Edate],[PersonID],[T_ID])values ('17/06/2005','24/06/2005',123,234)INSERT INTO [Tbl1]([Sdate],[Edate],[PersonID],[T_ID])values ('17/06/2005','24/06/2005',122,232)INSERT INTO [Tbl1]([Sdate],[Edate],[PersonID],[T_ID])values ( '11/06/2005','27/06/2005',125,235 )INSERT INTO [Tbl1]([Sdate],[Edate],[PersonID],[T_ID])values ( '09/06/2005','24/06/2005',127,234 )INSERT INTO [Tbl1]([Sdate],[Edate],[PersonID],[T_ID])values ( '11/06/2005','24/06/2005',128,238 )INSERT INTO [Tbl1]([Sdate],[Edate],[PersonID],[T_ID])values ( '17/06/2006','27/06/2006',129,234 )INSERT INTO [Tbl1]([Sdate],[Edate],[PersonID],[T_ID])values ( '22/06/2006','24/06/2006',143,237 )INSERT INTO [Tbl1]([Sdate],[Edate],[PersonID],[T_ID])values ( '26/06/2005','29/06/2005',163,234 )INSERT INTO [Tbl1]([Sdate],[Edate],[PersonID],[T_ID])values ( '28/06/2005','03/07/2005',163,235 )INSERT INTO [Tbl1]([Sdate],[Edate],[PersonID],[T_ID])values ( '23/06/2005','28/06/2005',143,232 )INSERT INTO [Tbl1]([Sdate],[Edate],[PersonID],[T_ID])values ( '17/06/2005','24/06/2005',124,234 )INSERT INTO [Tbl1]([Sdate],[Edate],[PersonID],[T_ID])values ( '23/06/2005','30/06/2005',125,231 )INSERT INTO [Tbl1]([Sdate],[Edate],[PersonID],[T_ID])values ( '24/06/2005','29/06/2005',123,238) INSERT INTO [Tbl1]([Sdate],[Edate],[PersonID],[T_ID])values ( '28/06/2005','03/07/2005',123,233) INSERT INTO [Tbl1]([Sdate],[Edate],[PersonID],[T_ID])values ( '03/06/2005','10/06/2005',125,231 )INSERT INTO [Tbl1]([Sdate],[Edate],[PersonID],[T_ID])values ( '28/08/2005','03/09/2005',123,233) INSERT INTO [Tbl1]([Sdate],[Edate],[PersonID],[T_ID])values ( '03/08/2005','10/08/2005',125,231 )goDeclare @sessionlength int -- number of days elapsed in a periodDeclare @sessionlengthtot int -- number of days elapsed in a periodDeclare @session_no int --counter to get the total periods for each sessionSET NOCOUNT ONDECLARE @person_id int, @sdate_ nvarchar(20),@edate_ nvarchar(20),@message varchar(100),@tid int, @product nvarchar(50),@person_id2 int, @sdate_2 nvarchar(20),@edate_2 nvarchar(20),@tid2 int,@sdate_3 datetime,@edate_3 datetime PRINT '-------- Sessions Report --------'DECLARE session_cursor CURSOR FOR SELECT DISTINCT PersonID,Sdate,Edate,T_ID from Tbl1 ORDER BY PersonID OPEN session_cursor FETCH NEXT FROM session_cursor INTO @person_id, @sdate_,@edate_ ,@tid set @sessionlengthtot = 0 WHILE @@FETCH_STATUS = 0 BEGIN PRINT ' ' SELECT @message = '----- periods and sessions for Person: ' + cast(@person_id as varchar(20)) PRINT @message-- Declare an inner cursor based -- on person_id from the outer cursor. DECLARE period_cursor CURSOR FOR SELECT pv.PersonID,pv.Sdate,pv.Edate,pv.T_ID FROM Tbl1 pv WHERE pv.Sdate <= @edate_ AND pv.PersonID = @person_id -- Variable values from the outer cursor ORDER BY CONVERT(DATETIME,pv.Sdate, 103),pv.PersonID OPEN period_cursor FETCH NEXT FROM period_cursor INTO @person_id2, @sdate_2,@edate_2 ,@tid2 set @sdate_3 = CONVERT(DATETIME,@sdate_2, 103) set @edate_3 = CONVERT(DATETIME,@edate_2, 103) -- todo - get the total sessionlength for all periods set @sessionlength = datediff("d",@sdate_3,@edate_3) IF @@FETCH_STATUS <> 0 PRINT ' <<None>>' WHILE @@FETCH_STATUS = 0 BEGIN SELECT @message = ' InDate: ' + @sdate_2 + ', OutDate: ' + @edate_2 + ', T_ID = ' + cast(@tid2 as varchar(20)) + ', days = ' + cast(@sessionlength as varchar(20)) PRINT @message FETCH NEXT FROM period_cursor INTO @person_id2, @sdate_2,@edate_2 ,@tid2 set @sdate_3 = CONVERT(DATETIME,@sdate_2, 103) set @edate_3 = CONVERT(DATETIME,@edate_2, 103) set @sessionlength = datediff("d",@sdate_3,@edate_3) END CLOSE period_cursor DEALLOCATE period_cursor -- Get the next PersonID. FETCH NEXT FROM session_cursor INTO @person_id, @sdate_,@edate_ ,@tid set @sessionlengthtot = 0 END CLOSE session_cursorDEALLOCATE session_cursorNow what I need to do is add up a running total of periods based upon criteria 'WHERE pv.Sdate <= @edate_ AND pv.PersonID = @person_id' |
 |
|
|
SwePeso
Patron Saint of Lost Yaks
30421 Posts |
|
|
|
|
|
|
|