Comparing Records

joycek

New member
Local time
Today, 13:50
Joined
Aug 14, 2006
Messages
7
Hi,

I need to compare records in the same table. I know that this is typically accomplished by joining the table with itself. However, this is not entirely suitable for my needs. I need to compare the first record to every other record - excluding itself - and then compare the second record to every other record excluding itself AND the first record. I want to continue this pattern for all the records. Is there any way I could go about doing this?
Any help would be much appreciated.

Edit: Each record has an autonumber generated key
 
Last edited:
I take it that this is either not possible or extremely difficult to implement...
 
I take it that this is either not possible or extremely difficult to implement...

It seems that comparing records is tougher than I thought too.

I've been trying to get help on the same subject for a long time.
 
It seems that comparing records is tougher than I thought too.

I've been trying to get help on the same subject for a long time.

Actually, after thinking about it, if you are needing to compare each field in a record to itself, it should be possible to utilize two recordsets and loop through them.

The biggest question is what are you wanting to compare, and why?
 
Actually, after thinking about it, if you are needing to compare each field in a record to itself, it should be possible to utilize two recordsets and loop through them.

The biggest question is what are you wanting to compare, and why?

Thank you Bob,

The current record to the one preceding it and the one immediately following without use of an ordered ID field. For example, I have two columns one for start time one for end time, I would like to compare the last end time to the current start time and the next start time to the current end time. I'd like the difference in times to appear in a third column called TimeLapse.

Note the list cannot have an ordered ID.
 
Can you post a copy of your db? Your PK is an AutoNumber correct?
 
Can you post a copy of your db? Your PK is an AutoNumber correct?

Thank you Keith,

The table/form in question is really intended to calculate the hours that contractors in a company spent working as well as the hours inbetween jobs. Here's a description of the objects involved:

Table: tblTimeSheet
Fields: Starttime, EndTime, HrsWrkd and TimeInBtwn.
Datatype: All of them are "text".

Form: frmTimeSheet
Controls: txtStartTime, txtEndTime, txtHrsWrkd and txtTimeInBtwn.


First of all, frmTimeSheet is bound to tblTimeSheet. Is it better for it to be bound to tblTimeSheet's select query for filtering purposes?

The difference between the current StartTime value and the current EndTime value must populate the HrsWrkd field, while the difference between the previous record's EndTime value and the current StartTime value becomes the TimeInBtwn value.

Unfortunately I can't use an autonumber primary Key to reference and calculate a particular worker's times because there is no pattern guaranteed: 15 workers all enter their times in one table, tblTimeSheet, and at random times.

Therefore, establishing the previous record values for a particular contractor using a Dlookup of the autonumber primary keyfield, ie. ID-1, is not possible. The previous record's EndTime can be that of any of the 15 workers: It is random.

Calculating the TimeInBtwn is crucial because if it's greater than 5 hours, the HrsWrkd value automatically defaults to 7 IF the HrsWrkd were less than 7. If the hrs worked were greater than 7, then the "real" hrs (actual difference between current StartTime and current EndTime) populate the HrsWrkd field. If the TimeInBtwn is less than five hrs, then HrsWrkd are always equal to current Endtime - StartTime.

I am using Access 2007 for this project - in case it matters.

I'll be be very grateful for any help, even a fraction of the solution. Ps, I am not very familiar with the declarations of DAO's and the Set bit.

Thank you in advance.
 
Last edited:
without use of an ordered ID field

Note the list cannot have an ordered ID.

Be exceedingly careful here. You are asking for something that technically does not exist in nature.

Let me explain. SQL is based on SET theory. SET theory does not have the concept of ORDER (with respect to the order of appearance of members). There IS no "NEXT" or "PREVIOUS" in terms of SET theory.

You MUST impose an order externally if this question is to make any sense at all. But you can impose the order via a query that looks at the very time fields you wanted to examine without creating a new record ID.

Now, there is a way to do what you want via VBA. The VBA would be run either through a form (in the form's class module run by an EVENT-based trigger) or a macro (from a general module using RunCode). Why VBA (you ask....)? Because SQL has no syntax for relative order of records. There IS no NEXT or PREVIOUS operator.

So... how to get there from here? With a query that imposes time-order on your dataset, you are halfway there. Write the VBA code to open the query's recordset once (perhaps as a dynaset, which you would look up using the Access Help Files). A dynaset can be updated from VBA code.

Then in a VBA loop that looks at each record in the query, you would store the current position by capturing the BOOKMARK propery of the recordset (q.v. in the Access Help Files). This would allow you to return to the bookmark later if you needed to. You can make a recordset clone (which you can look up in the help files) to have two streams in the same recordset.

You can use the BOOKMARK, .MOVENEXT, and .MOVEPREV methods on the recordset - which works in VBA because VBA is NOT an SQL entity. IN THAT CONTEXT, there is such a thing as capturing the data you want to keep, stepping to another record, and doing a comparison. Because VBA is OUTSIDE of the actions normally allowed to SQL.

I'll add one more bit of clarification. In the original derivation of the laws of set theory that led to creation of SQL, the implementation was left to the vendor but the idea was that when an SQL statement was complete, all records in the set were treated in the same way. Inherent in that historical setup was that the user of SQL could not see and should not care in what order a particular set of actions occurred, which is the point that justifies omitting NEXT and PREVIOUS keywords. To you, SQL is a monolithic, all-records-at-once operation. Which is why you need to use something like VBA that can get into the vendor's implementation by low-level methods.
 
I see a problem with how your database is setup. Did you include all fields from tblTimeSheet? I don't see any PK (Primary Key) or FK (Foreign keys) in the table schema. Also there is really no need to store a calculated field.
 
Be exceedingly careful here. You are asking for something that technically does not exist in nature.

Let me explain. SQL is based on SET theory. SET theory does not have the concept of ORDER (with respect to the order of appearance of members). There IS no "NEXT" or "PREVIOUS" in terms of SET theory.

You MUST impose an order externally if this question is to make any sense at all. But you can impose the order via a query that looks at the very time fields you wanted to examine without creating a new record ID.

Now, there is a way to do what you want via VBA. The VBA would be run either through a form (in the form's class module run by an EVENT-based trigger) or a macro (from a general module using RunCode). Why VBA (you ask....)? Because SQL has no syntax for relative order of records. There IS no NEXT or PREVIOUS operator.

So... how to get there from here? With a query that imposes time-order on your dataset, you are halfway there. Write the VBA code to open the query's recordset once (perhaps as a dynaset, which you would look up using the Access Help Files). A dynaset can be updated from VBA code.

Then in a VBA loop that looks at each record in the query, you would store the current position by capturing the BOOKMARK propery of the recordset (q.v. in the Access Help Files). This would allow you to return to the bookmark later if you needed to. You can make a recordset clone (which you can look up in the help files) to have two streams in the same recordset.

You can use the BOOKMARK, .MOVENEXT, and .MOVEPREV methods on the recordset - which works in VBA because VBA is NOT an SQL entity. IN THAT CONTEXT, there is such a thing as capturing the data you want to keep, stepping to another record, and doing a comparison. Because VBA is OUTSIDE of the actions normally allowed to SQL.

I'll add one more bit of clarification. In the original derivation of the laws of set theory that led to creation of SQL, the implementation was left to the vendor but the idea was that when an SQL statement was complete, all records in the set were treated in the same way. Inherent in that historical setup was that the user of SQL could not see and should not care in what order a particular set of actions occurred, which is the point that justifies omitting NEXT and PREVIOUS keywords. To you, SQL is a monolithic, all-records-at-once operation. Which is why you need to use something like VBA that can get into the vendor's implementation by low-level methods.

Doc

This is a very informative post. Thank you very much.

I will try out the bookmarking tips after some further reading on how.
 
I see a problem with how your database is setup. Did you include all fields from tblTimeSheet? I don't see any PK (Primary Key) or FK (Foreign keys) in the table schema. Also there is really no need to store a calculated field.


Yes Keith, I did (foolishly) forget to mention my ID field. The tblTimeSheet does in fact have a Primary Key. However, after the filter is applied in the form (according to the worker's name), the number ID's rise with each row but by unpredictable changes.

I suspected that the calculated field was redundant because of the figure also appearing in the form and so I'll definitely eliminate it.

I have seen a code that did part of what I am attempting to do but I kept failing to apply it to my own form.

I'll post the code in a bit.
 
This was a problem someone else proposed on a different site.

Greetings. I need help writing a Query or Visual Basic code in MS
Access.

I'm not sure which is the solution.

I'm trying to create a table that will find the next and previous
sequential records in a table. Additionally, this query (or VBA) would
append text to the text value of the 'next' and previous' record, in
this case "p-."

[SKU] is given, [PREVIOUS] and [NEXT] are calculated based on [SKU].
Note fieldnames have been bracketed.

When properly calculated, the newly created table would look something
like this:

[SKU] [PREVIOUS] [NEXT]
B0587159901 p-B0587159979 p-B058715991X
B058715991X p-B0587159901 p-B0587159928
B0587159928 p-B058715991X p-B0587159936
B0587159936 p-B0587159928 p-B0587159944
B0587159944 p-B0587159936 p-B0587159952
B0587159952 p-B0587159944 p-B0587159960
B0587159960 p-B0587159952 p-B0587159979
B0587159979 p-B0587159960 p-B0587159901

Note: For the first record [SKU], the [PREVIOUS] field would show the
last record. For the last record [SKU], the [NEXT] field would show
the first record. Also, the [SKU] numbers are NOT in any ascending or
decending order. In the live application, they are in a random order
(and must stay that way), so the solution must involving getting the
next and previous record, rather than a <> solution.

I've posted this question on the MrExcel.com bulletin board, but could
not get a decent solution to my problem. Read more here.
http://www.mrexcel.com/board2/viewtopic.php?t=49897&highlight=

If there is any additional information needed to clarify this
question, please ask.

Please let me know if writing the VBA involves more than a few lines
of code and I will tip accordingly.

Any help would be greatly appreciated.







And the following is a solution someone else proposed...









Here is a VBA routine for you. Paste it into a new Access module. The
routine assumes that you have two tables already existing:

Table: tblSKU
Field Name Type
-------------------------------
SKU Text Primary Key

Table: tblLinkedList
Field Name Type
------------------------------
SKU Text Primary Key
PreviousSKU Text
NextSKU Text


NOTE: No line of code should wrap. Code may need to be unwrapped after
pasting into a VBA module.

' ****** Code Begin

Public Sub BuildLinkedList()
On Error GoTo ErrHandler

Dim cnn As ADODB.Connection
Dim rstSKU As ADODB.Recordset
Dim rstSKUClone As ADODB.Recordset
Dim strSQL As String
Dim strSKU As String
Dim strPrev As String
Dim strNext As String
Dim strFirstSKU As String
Dim strLastSKU As String

Set cnn = CurrentProject.Connection
Set rstSKU = New ADODB.Recordset

' Clear existing records from table
cnn.Execute ("DELETE * FROM tblLinkedList;")

' Select all SKUs in the order they currently
' appear in the SKU table. No sort is applied.
strSQL = "SELECT SKU FROM tblSKU;"
rstSKU.Open strSQL, cnn, adOpenStatic, adLockOptimistic
strSQL = ""
If Not rstSKU.BOF And Not rstSKU.EOF Then
rstSKU.MoveFirst
' Set first and last value for
' looparound
strFirstSKU = "p-" & rstSKU!SKU
rstSKU.MoveLast
strLastSKU = "p-" & rstSKU!SKU
rstSKU.MoveFirst
' Clone the recordset so we can
' keep two bookmarks
Set rstSKUClone = rstSKU.Clone
rstSKUClone.MoveNext
' Now rstSKU is on the first record and
' rstSKUClone is on the 'next' record.

strPrev = strLastSKU
Do Until rstSKU.EOF
strSKU = rstSKU!SKU
If Not rstSKUClone.EOF Then
strNext = "p-" & rstSKUClone!SKU
rstSKUClone.MoveNext
Else
strNext = strFirstSKU
End If
strSQL = "INSERT INTO tblLinkedList (SKU, PreviousSKU,
NextSKU) VALUES ('" & strSKU & "', '" & strPrev & "', '" & strNext &
"');"
cnn.Execute (strSQL)
strPrev = "p-" & rstSKU!SKU
rstSKU.MoveNext
Loop
End If

ExitMe:
' Clean up memory
strSQL = ""
strSKU = ""
strPrev = ""
strNext = ""
strFirstSKU = ""
strLastSKU = ""
If rstSKUClone.State = adStateOpen Then
rstSKUClone.Close
End If
Set rstSKUClone = Nothing
If rstSKU.State = adStateOpen Then
rstSKU.Close
End If
Set rstSKU = Nothing
Set cnn = Nothing
Exit Sub

ErrHandler:
MsgBox Err.Description
Resume ExitMe

End Sub
 
I was very happy to find the above solution to a problem similar to mine...until I tried the solution using the tables in its example and also copying and pasting the code into a new standard module.

Just to test it out, I made tblSKU and tblLinkedList along with the fields and datatypes used in the example, opened a new standard module and pasted the code in it.

I was expecting that the previous records and next records would appear in the appropriate fields of tblLinkedList when I'd open it, yet nothing happened.

I tried running the module from Visual Basics (Run ->Run sub/userform) and got this message:

Compile error: User-defined type not defined.

Do you know how to avoid it? And was I supposed to do something else, maybe start a form bound to one of the two tables and then place this code in the form?

If you could just advise me where I went wrong in my "testing" of this code or what exactly I am overlooking, what I left out or misunderstood, I am certain I would be 3/4 of the way there.

Once again, I am very appreciative for the helpful advice. Thank you.

Ps, I am using Access 2007.
 

Users who are viewing this thread

Back
Top Bottom