Home | Contact Us | FAQ | Search & Site Map | Link to Us
Sign In | Join | Other 45 Sites in Network
Home
Discussion GroupsFormsForms ProgrammingQueriesModules / DAO / VBAReports / PrintingMacrosDatabase DesignSecurityConversionImporting / LinkingSQL Server / ADPMultiuser / NetworkingReplicationSetup / ConfigurationDeveloper ToolkitsActiveX ControlsNew UsersGeneral 1General 2
Access DirectoryToolsTutorialsUser Groups
Related Topics
SQL ServerOther DB ProductsMS OfficeMore Topics ...

MS Access Forum / Queries / April 2008

Tip: Looking for answers? Try searching our database.

updating a sorted numerical field to absolute position in recordset?

Thread view: 
Enable EMail Alerts  Start New Thread
Thread rating: 
gerardianlewis@yahoo.com - 27 Apr 2008 05:04 GMT
Suppose you have an auxiliary table that looks like this:

IdWidget(Autonumber, primary key)
Widget (text)
Some other fields
SortOrder (Long Integer)

Your application first empties the table, then fills it with records,
The SortOrder field at this point contains zeroes. In response to user
interaction, this field is then updated with a series of values based
on some complex calculations involving values in other tables. These
resulting SortOrder numbers reflect the order that the records should
be presented in, but for various reasons they are not consecutive. For
example:

Widget         SortOrder
aabb             2
xxcc             3
aaxx             54
ddee             244

etc.

Now, obviously a simple SORT BY SortOrder will present the resultset
in the correct order, but for various boring reasons I want to be able
to update the contents of the SortOrder field so that the numbers
start at 1 and are consecutive, like so:

Widget         SortOrder
aabb             1
xxcc             2
aaxx             3
ddee             4

The easiest way to do this is to run a series of UPDATE queries inside
a loop to update the records one at a time, feeding the loop counter
through as a parameter. But this is slow and inefficient. It strikes
me there ought to be a way to do the entire update in one query. As an
experiment, I wrote a SELECT query that presented the numbers I wanted
to poke into the SortOrder field, and it worked fine: I simply added,
inside my main query, a calculated field containing a SELECT statement
like this (I'm omitting the brackets for clarity):

MyCalcField: (SELECT Count(w.Widget) FROM Widgets AS w WHERE
w.SortOrder <= Widgets.SortOrder)

In other words, for each record, simply add up the number of records
in the same table where SortOrder <= the SortOrder of the current
record. Unfortunately, while this works for a SELECT, it doesn't work
for an UPDATE: if you turn this SELECT into an update, Access returns
a message saying something like "you need to use an updateable query"
and refuses to execute it. I tried rewriting the update query using
DCount(widget) etc, but while the query executed without problems, the
results weren't as expected: some ordinals were missed out and others
were duplicated, presumably because the calculation of DCount isn't
done in advance but is alternated with the updating.

Am I going to have to add a new field to the table to store
intermediate values and run two queries (one to poke the ordinals into
MyUglyTempField and the other to copy them over to SortOrder), or is
there some more elegant method I haven't thought of?

TIA
Evi - 27 Apr 2008 14:46 GMT
I use recordset code to do this. I run it by pressing a button in my form.
Mine looks like this

Private Sub cmbRenumberTracks_Click()
Dim a As Integer
Dim MyTable As String
Dim Db As Database
Dim rs As Recordset

MyTable = "QryRenumberTracks"
'This query  is sorted in Num  order
'Num is a number field
'(though not a primary key field)
Set Db = CurrentDb
Set rs = Db.OpenRecordset(MyTable, dbOpenDynaset)
a = 1
rs.MoveFirst
'go to first record in MyTable
Do Until rs.EOF
'stop when you get to the end of MyTable
       rs.Edit
       rs!Num = a
   'Update my Num field
       rs.Update
       rs.MoveNext
       a = a + 1
Loop

rs.Close
Set rs = Nothing
Set Db = Nothing
End Sub

Evi
> Suppose you have an auxiliary table that looks like this:
>
[quoted text clipped - 59 lines]
>
> TIA
gerardianlewis@yahoo.com - 27 Apr 2008 15:27 GMT
> I use recordset code to do this. I run it by pressing a button in my form.
> Mine looks like this
[quoted text clipped - 28 lines]
> Set Db = Nothing
> End Sub

Yes, well, that's close to what I already had, an update inside a loop
- except I use ADO.NET rather than DAO to communicate with the DB. (I
liked DAO better, it was more flexible and I suspect a lot faster, but
it's not being supported any more, so...). As I said, I'm looking for
a solution that doesn't use a loop in code, as when you're updating
several thousand records, let alone tens of thousands,  the
sluggishness starts to show. If no one else replies I'll probably go
for the two-stage solution using an extra field in the table for the
purpose.

Thanks for replying.

> Evi<gerardianle...@yahoo.com> wrote in message
>
[quoted text clipped - 65 lines]
>
> - Show quoted text -
John Spencer - 27 Apr 2008 21:11 GMT
If the calculated sortorder value is unique to start with then one
option is to build a separate table with the old number and the ranking
number

SELECT SortOrder,
Count(B.SortOrder) as NewOrder
FROM WidgetTable as A LEFT JOIN WidgetTable As B
ON A.SortOrder < B.SortOrder
GROUP BY SortOrder

Use that query to populate a work table.

Now use the work table to populate the sort order in the widgets table
UPDATE Widgets Inner Join WorkTable
on Widgets.SortOrder = WorkTable.SortOrder
SET Widgets.SortOrder = [WorkTable].[NewOrder] + 1

With a large number of records this will probably be the most efficient
manner of doing the update.  The big problem here is that it won't
handle ties if two records have the same calculated sortorder value.  In
the case of ties all the tied records will end up with the same new
value and there will be a gap in the sequence.

'====================================================
 John Spencer
 Access MVP 2002-2005, 2007-2008
 Center for Health Program Development and Management
 University of Maryland Baltimore County
'====================================================

> Suppose you have an auxiliary table that looks like this:
>
[quoted text clipped - 59 lines]
>
> TIA
gerardianlewis@yahoo.com - 28 Apr 2008 00:32 GMT
> If the calculated sortorder value is unique to start with then one
> option is to build a separate table with the old number and the ranking
[quoted text clipped - 92 lines]
>
> - Show quoted text -

Thanks for replying. I agree, it looks like doing the update in two
shots is the best we can do here, either using a separate table or an
extra field in the same table (since the original table in question is
a work table anyway, and gets periodically emptied, having an extra
field in it isn't such a big deal).

The question of duplicate SortOrder values doesn't arise in this case,
but I guess that would complicate matters.
John Spencer - 28 Apr 2008 12:34 GMT
My method won't allow you to update the widget table directly.  It uses an
aggregate in the first query to generate the ranking number (one up number).

In Access, you can never update a table using an aggregate (totals) query as
the source (or destination).  If you could then the two-step method I proposed
would not be needed.

Good luck

John Spencer
Access MVP 2002-2005, 2007-2008
Center for Health Program Development and Management
University of Maryland Baltimore County

>> - Show quoted text -
>
[quoted text clipped - 6 lines]
> The question of duplicate SortOrder values doesn't arise in this case,
> but I guess that would complicate matters.
 
Sign In
Join
My Latest Posts
My Monitored Threads
My Blog
My Photo Gallery
My Profile
My Homepage

Start New Thread
Enable EMail Alerts
Rate this Thread



©2009 Advenet LLC   Privacy Policy - Terms of Use
This website includes both content owned or controlled by Advenet as well as content owned or controlled by third parties.