473,394 Members | 1,794 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,394 software developers and data experts.

Grouping records by time period

Hi all,

I have a table with a date/time and a name. If I have a record for example with John as the name and the time is 12:00, can I replace any further instances of John with N/A for the next hour? All I need is the 1st instance of each name for the following hour. I can then filter by excluding N/A to shrink the amount of records in the query.

12:00 John
12:01 Simon
12:03 John (needs to be replaced by N/A)
12:04 John (needs to be replaced by N/A)
12:05 Jack
13:03 John (This can remain as more than 1 hour since the previous instance of the name)
13:05 John (needs to be replaced by N/A as less than 1 hour since the one at 13:03)

The above query would then be 4 records in total instead of 7.

All I have done so far is being able to filter names that are immediately afterwards but not if there any record in the middle

MyName: IIf(DLookUp("[Name1]","Name_Table","[ID]=" & [ID]-1)=[Name1],"N/A",[Name1])

This works ok but it obviously does not filter all the records I need. Would appreciate if anyone has any suggestions if this is possible.

Thanks in advance.

Gareth
Jul 8 '14 #1

✓ answered by twinnyfo

Gareth,

This will do what you want it to do.... My assumptions were a Table namees tblCallOutHistory with two fields: TimeStamp And Technician.

Expand|Select|Wrap|Line Numbers
  1. Public Function UpdateCallOuts()
  2. On Error GoTo EH:
  3.     Dim db As Database
  4.     Dim rstNames As Recordset
  5.     Dim rstCallOuts As Recordset
  6.     Dim strSQL As String
  7.     Dim dtmFirstCallout As Date
  8.     Set db = CurrentDb()
  9.     strSQL = "SELECT Technician " & _
  10.         "FROM tblCallOutHistory " & _
  11.         "GROUP BY Technician " & _
  12.         "HAVING Technician <> 'N/A';"
  13.     Set rstNames = db.OpenRecordset(strSQL, dbOpenDynaset)
  14.     If Not rstNames.RecordCount = 0 Then
  15.         rstNames.MoveFirst
  16.         Do While Not rstNames.EOF
  17.             strSQL = "SELECT * " & _
  18.                 "FROM tblCallOutHistory " & _
  19.                 "WHERE Technician = '" & rstNames!Technician & "' " & _
  20.                 "ORDER BY TimeStamp;"
  21.             Set rstCallOuts = db.OpenRecordset(strSQL, dbOpenDynaset)
  22.             If Not rstCallOuts.RecordCount = 0 Then
  23.                 rstCallOuts.MoveFirst
  24.                 dtmFirstCallout = rstCallOuts!TimeStamp
  25.                 rstCallOuts.MoveNext
  26.                 Do While Not rstCallOuts.EOF
  27.                     If DateAdd("n", -60, rstCallOuts!TimeStamp) > dtmFirstCallout Then
  28.                         dtmFirstCallout = rstCallOuts!TimeStamp
  29.                     Else
  30.                         With rstCallOuts
  31.                             .Edit
  32.                             !Technician = "N/A"
  33.                             .Update
  34.                         End With
  35.                     End If
  36.                     rstCallOuts.MoveNext
  37.                 Loop
  38.             End If
  39.             rstNames.MoveNext
  40.         Loop
  41.     End If
  42.     Exit Function
  43. EH:
  44.     MsgBox Err.Number & ":  " & Err.Description
  45.     Exit Function
  46. End Function
I made this a public function so I could test it. If you would rather delete the call outs that are all within one hour of the first call out, then replace lines 30-34 with the following:

Expand|Select|Wrap|Line Numbers
  1.                         With rstCallOuts
  2.                             .Delete
  3.                         End With
Some things to think about: While this code will work and do what you want it to do, you should be aware that this will cycle through all records in your table, every time you want to check the call out times. This is not a big deal if you only have a few records, but if you keep records for several years, this could become a burden. Then you might want to add a new field, perhaps "Verified" as a Yes/No Field which would get updated when the code is run, then you change the Select Statement to filter out any verified records, then it only cycles through the records it needs to.

Second, if your DB is properly normalized, which is should be if it is not already, then remember that the SELECT Statements referring to the technician should be pointing to an index in another table (tblTechnicians). This is a good practice to get into, especially in the long run as you continue to develop and expand your project (we always do....). For some initial details about DB normalization, look here.

Hope this helps, but keep in mind, there may be better ways to manage what you are trying to do. However, based on what you want and how you want to do it, this solution may be helpful.

15 1405
twinnyfo
3,653 Expert Mod 2GB
Gareth,

It perhaps would be helpful if we understood what you are trying to do in the bigger scheme of things. I think there are ways of doing what you want to do, but there may be better ways of doing this if we understood why you needed such a grouping. There may be better ways of doing what you are trying to do, besides changing the names to "N/A".
Jul 8 '14 #2
Thanks for replying.

Its essentially to do with Overtime. If someone has been called for a problem, it is classed as a callout. If they get a few more calls within an hour of this initial call, then it is classed as the same problem/callout. If any further calls are received after an hour, the process starts again and the first of these new calls is classed as a callout.

The hour figure is not set in stone, however once the functionality works, this figure can always be changed.

Thanks
Jul 8 '14 #3
twinnyfo
3,653 Expert Mod 2GB
One method for dealing with this situation, might be to check the status of the technician's most recent call out and see if it has been more than an hour since. If not, then don't add a new record. However, from a management standpoint, I would think you would want to keep track of the number of calls, as well as the actual time.

I have some ideas on how to work this, but I would also need to know how this information is going to be used, such as, is it just going to be printed on a report. Do you need to know about the multiple calls, but just calcluate pay based on the time span? The reason I ask, is that there may be value in maintaining the name of the technician in your Table, but identifying the records you want to work from in a different way. Remember, by changing the name to "N/A", in your example, they are all "John", but could just as well be Jack or Simon.

Forgive me for asking more questions, but I want to make sure we guide you down a good path, not just one that will get you to a solution.
Jul 8 '14 #4
I appreciate you taking the time to look into this. All the calls are kept in the master table so for the purpose of this query, they can be filtered out completely. For every name, whether its John or Simon etc, the same rule applies, only display the first callout, filter the next hour's worth out and then start the process again.

Thanks
Jul 8 '14 #5
twinnyfo
3,653 Expert Mod 2GB
Gareth,

This will do what you want it to do.... My assumptions were a Table namees tblCallOutHistory with two fields: TimeStamp And Technician.

Expand|Select|Wrap|Line Numbers
  1. Public Function UpdateCallOuts()
  2. On Error GoTo EH:
  3.     Dim db As Database
  4.     Dim rstNames As Recordset
  5.     Dim rstCallOuts As Recordset
  6.     Dim strSQL As String
  7.     Dim dtmFirstCallout As Date
  8.     Set db = CurrentDb()
  9.     strSQL = "SELECT Technician " & _
  10.         "FROM tblCallOutHistory " & _
  11.         "GROUP BY Technician " & _
  12.         "HAVING Technician <> 'N/A';"
  13.     Set rstNames = db.OpenRecordset(strSQL, dbOpenDynaset)
  14.     If Not rstNames.RecordCount = 0 Then
  15.         rstNames.MoveFirst
  16.         Do While Not rstNames.EOF
  17.             strSQL = "SELECT * " & _
  18.                 "FROM tblCallOutHistory " & _
  19.                 "WHERE Technician = '" & rstNames!Technician & "' " & _
  20.                 "ORDER BY TimeStamp;"
  21.             Set rstCallOuts = db.OpenRecordset(strSQL, dbOpenDynaset)
  22.             If Not rstCallOuts.RecordCount = 0 Then
  23.                 rstCallOuts.MoveFirst
  24.                 dtmFirstCallout = rstCallOuts!TimeStamp
  25.                 rstCallOuts.MoveNext
  26.                 Do While Not rstCallOuts.EOF
  27.                     If DateAdd("n", -60, rstCallOuts!TimeStamp) > dtmFirstCallout Then
  28.                         dtmFirstCallout = rstCallOuts!TimeStamp
  29.                     Else
  30.                         With rstCallOuts
  31.                             .Edit
  32.                             !Technician = "N/A"
  33.                             .Update
  34.                         End With
  35.                     End If
  36.                     rstCallOuts.MoveNext
  37.                 Loop
  38.             End If
  39.             rstNames.MoveNext
  40.         Loop
  41.     End If
  42.     Exit Function
  43. EH:
  44.     MsgBox Err.Number & ":  " & Err.Description
  45.     Exit Function
  46. End Function
I made this a public function so I could test it. If you would rather delete the call outs that are all within one hour of the first call out, then replace lines 30-34 with the following:

Expand|Select|Wrap|Line Numbers
  1.                         With rstCallOuts
  2.                             .Delete
  3.                         End With
Some things to think about: While this code will work and do what you want it to do, you should be aware that this will cycle through all records in your table, every time you want to check the call out times. This is not a big deal if you only have a few records, but if you keep records for several years, this could become a burden. Then you might want to add a new field, perhaps "Verified" as a Yes/No Field which would get updated when the code is run, then you change the Select Statement to filter out any verified records, then it only cycles through the records it needs to.

Second, if your DB is properly normalized, which is should be if it is not already, then remember that the SELECT Statements referring to the technician should be pointing to an index in another table (tblTechnicians). This is a good practice to get into, especially in the long run as you continue to develop and expand your project (we always do....). For some initial details about DB normalization, look here.

Hope this helps, but keep in mind, there may be better ways to manage what you are trying to do. However, based on what you want and how you want to do it, this solution may be helpful.
Jul 8 '14 #6
Rabbit
12,516 Expert Mod 8TB
Here is a SQL only solution. It was created in SQL Server but is portable to Access.
Expand|Select|Wrap|Line Numbers
  1. SELECT
  2.     uname,
  3.     MIN(dt) AS dt
  4.  
  5. FROM 
  6.     (
  7.         SELECT
  8.             t1.uname,
  9.             t1.dt,
  10.             MIN(t2.dt) AS mdt
  11.  
  12.         FROM 
  13.             #t t1
  14.  
  15.             LEFT JOIN #t t2
  16.             ON    t1.uname = t2.uname AND
  17.                 t1.dt > t2.dt
  18.  
  19.         WHERE
  20.             DATEDIFF(MINUTE, t2.dt, t1.dt) >= 60 OR
  21.             t2.dt IS NULL
  22.  
  23.         GROUP BY
  24.             t1.uname,
  25.             t1.dt
  26.     ) t
  27.  
  28. GROUP BY
  29.     uname,
  30.     mdt
  31.  
  32. ORDER BY
  33.     dt
Jul 8 '14 #7
twinnyfo
3,653 Expert Mod 2GB
So, Rabbit, as usual, you amaze me! Could you help us mere mortals understand the nature of your SQL statement, particularly as it pertains to the "t", "#t", "t1" and "t2" stuff?

I think, I kinda mostly understand the rest of your solution, but it is meaningless without understanding how you got there. Obviously the aliens abducted you several years ago and imparted some special knowledge to you....


;-)
Jul 8 '14 #8
Rabbit
12,516 Expert Mod 8TB
Don't be amazed just yet lol. I just did some more testing and realized it only works with the given dataset. It stops working as soon as you add in another hour.
Jul 8 '14 #9
Thats brilliant thanks but for some reason I am getting no results back at the moment. Is it to be used in the criteria for the Technician field as in:
WHERE (((tblCallOuts.technician)=UpdateCallOuts()))
Jul 8 '14 #10
twinnyfo
3,653 Expert Mod 2GB
Gareth,

The Function UpdateCallOuts() in Post #6 does the updating for you, and does not return any values, so cannot be used as a criteria for a SELECT Statement, as you have used it. It will do all the updating by itself, leaving you only a list of Technicians and "N/A" (or delete the records completely).

Hope this helps your understanding of the code.

However, if Rabbit gets his wicked code working, he may have a better solution. But, again, we don't know exactly how you are going to use your list of names, whether it is in the table itself or a report, or whatever.
Jul 8 '14 #11
Rabbit
12,516 Expert Mod 8TB
I've tried but failed. It's doable with a cursor but Access SQL doesn't have cursors.
Jul 8 '14 #12
No wonder I couldnt get any values back :)

I tried just running the function itself and runs without any errors however does not appear to update the table at the moment
Jul 8 '14 #13
twinnyfo
3,653 Expert Mod 2GB
Your table/field names are properly coded into your VBA? I tested it on a table based on your first post and it ran without a hitch.
Jul 8 '14 #14
I tried again after re-compiling and it works perfect. Thanks both for your help. Appreciate it :)
Jul 8 '14 #15
twinnyfo
3,653 Expert Mod 2GB
Glad we could help! Hope you have a great day!
Jul 8 '14 #16

Sign in to post your reply or Sign up for a free account.

Similar topics

3
by: CrystalDBA | last post by:
I am using SQL Server 2000. I need to query my database for all the contracts that came in during a certain time frame (user is prompted for reportingperiodid). Table - Periods Fields -...
6
by: cjm | last post by:
I need to group records and assign a setid to the group. I have a table with data that looks like this ColA ColB 94015 01065 94016 01065 94015 01085 94015 01086 33383 00912 32601 00912
3
by: Dave | last post by:
Hi I am hoping someone might be able to help me out with this. I am writing a helpdesk system which records agents logging in and out of the system. I need to write a stored procedure which...
1
by: MLH | last post by:
I have a challenge... In a table I call tblStuff4Letters with 3 fields: , and . I have a report called rptOutboundCorrespondence that feeds off this table. Sorting & grouping is turned on in...
4
by: CH | last post by:
Hi, I recently encountered a problem while trying to create a report grouped by certain time frames. However, Access only allows grouping in Minutes or Hours. For example, the first time frame is...
6
by: craig.buchinski | last post by:
Ok, i have a Access Database (which is used with my ESRI Arcmap) and i have written a query for a report to pull out our streetlights and group them by billing wattage. The problem is that it is...
1
by: dianatokatlidis | last post by:
Hello. I have 2 separate date fields in a query. One is called Effective_Date and the other is called Expiry_Date. I want to compare the time period between these 2 fields and select any records...
1
by: Charming12 | last post by:
Hi All, I am facing quite a unique problem here with DayLight saving time. I know Windows handles Daylight saving time internally to sync PC Clock . But now i need to pass the Information of...
1
by: sasasasa | last post by:
How can I loop through each date in a given time period so that I can add those dates as a column name in a table. I want to create datatable with the person's name and hours he worked in a given...
1
by: jdsbuddy | last post by:
I'm an intermediate user of Access with a little SQL knowledge. I have a query I need and I'm not sure how to create it. I've one field that has 3 choices ... Approved, Denied, Pending. The...
0
by: Charles Arthur | last post by:
How do i turn on java script on a villaon, callus and itel keypad mobile phone
0
by: ryjfgjl | last post by:
If we have dozens or hundreds of excel to import into the database, if we use the excel import function provided by database editors such as navicat, it will be extremely tedious and time-consuming...
0
by: emmanuelkatto | last post by:
Hi All, I am Emmanuel katto from Uganda. I want to ask what challenges you've faced while migrating a website to cloud. Please let me know. Thanks! Emmanuel
1
by: nemocccc | last post by:
hello, everyone, I want to develop a software for my android phone for daily needs, any suggestions?
1
by: Sonnysonu | last post by:
This is the data of csv file 1 2 3 1 2 3 1 2 3 1 2 3 2 3 2 3 3 the lengths should be different i have to store the data by column-wise with in the specific length. suppose the i have to...
0
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However,...
0
by: Hystou | last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can...
0
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers,...
0
tracyyun
by: tracyyun | last post by:
Dear forum friends, With the development of smart home technology, a variety of wireless communication protocols have appeared on the market, such as Zigbee, Z-Wave, Wi-Fi, Bluetooth, etc. Each...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.