7

I believe similar questions have been asked but I can't quite find a solution that works for me.

I've got a database that I use to sort through digitised books and their pages and I'm trying to sort through several thousand pages that contain maps. Of the two tables I'm using the first lists all the pages in a book and the order they occur in the book, it's got three columns (bookID, pageOrder, pageID), each page has its own row. The second table lists all the places (in a map) that occur on each page, it has two columns (pageID, placeID) if there are multiple places on one page then a new row is added to the table for each place.

What I need to do is create a select statement that gives every pageID/placeID combination a unique number but the numbers must go in the order they appear in the book. In SQL Server I would do this:

SELECT ROW_NUMBER() OVER(ORDER BY bp.bookID, bp.pageOrder, pp.placeID) AS uniqueNumber, pp.pageID, pp.placeID
FROM booksAndPages AS bp INNER JOIN pagesAndPlaces AS pp ON bp.pageID = pp.pageID

Unfortunately, I'm stuck using Access. Ideally I'd like to do it (if possible) with a single SQL statement, similar to the one above but I would also try it using VBA.

Any help is greatly appreciated.

user2770656
  • 71
  • 1
  • 1
  • 2
  • Check this solution (see solution 2 regarding DCount()) http://stackoverflow.com/questions/17279320/row-numbers-in-query-result-using-microsoft-access – cha Sep 12 '13 at 00:37

3 Answers3

4

This is the query that you want:

SELECT ROW_NUMBER() OVER (ORDER BY bp.bookID, bp.pageOrder, pp.placeID) AS uniqueNumber,
       pp.pageID, pp.placeID
FROM booksAndPages AS bp INNER JOIN
     pagesAndPlaces AS pp
     ON bp.pageID = pp.pageID;

You can get the same result using a correlated subquery. More complicated and more expensive, but possible:

SELECT (select count(*)
        from booksAndPages AS bp2 INNER JOIN
             pagesAndPlaces AS pp2
             ON bp2.pageID = pp2.pageID
        where bp2.bookID < bp.bookID or
              (bp2.bookID = bp.bookID and bp2.pageOrder < bp.pageOrder) or
              (bp2.bookID = bp.bookID and bp2.pageOrder = bp.pageOrder and
               bp2.placeId <= pp.PlaceId
              )
       ) as uniqueNumber,
       pp.pageID, pp.placeID
FROM booksAndPages AS bp INNER JOIN
     pagesAndPlaces AS pp
     ON bp.pageID = pp.pageID;

This assumes that the combination bookId, pageOrder, placeId` is unique.

Gordon Linoff
  • 1,242,037
  • 58
  • 646
  • 786
1

I know this is an old question, but this was a top search and I haven't seen any other solutions on the internet so I hope this will help others.

My solution works for any dataset regardless of if it has a unique identifier or not.

Add the following VBA code into a module:

Public row as Variant

Function RowNum(dummy) As Integer
    row = row + 1
    RowNum = row
End Function

Function GetRowNum(dummy) As Integer
    GetRowNum = row
End Function

Function ResetRowNum()
    row = 0
End Function

Now here's a sample query:

SELECT Table1.Field1, Table1.Field2, RowNum([Field1]) AS RowId, 
    "Row: "&GetRowNum([Field1]) AS RowText
FROM Table1

You can add any 'ORDER BY' or even 'GROUP BY' if you wish. You can use any field that will be in the query output as the input for RowNum and GetRowNum. Important to note is to only use RowNum for the first time you want the row number and use GetRowNum every time after. This is to prevent one row increasing the counter more than once.

The last thing you need to do is create a macro that runs ResetRowNum and run it after every query you use with this method, or if you're running a series of queries through a macro or VBA, make sure to run ResetRowNum after every query that uses these functions.

Also avoid datasheet view, as it seems to constantly recalculate the formulas when you scroll, making the numbers steadily increase.

Aehetag
  • 36
  • 2
  • Your `RowNum` function could take a second optional Boolean parameter for when the row shouldn't be advanced. That would obviate the need for the `GetRowNum` function. – Zev Spitz Mar 03 '16 at 07:58
-2

Query to sort and/or group

SELECT Table1.Field1, 
       Table1.SomeDate, 
       Table1.Field2,
       RowNumber([Field1]) AS RowId,
       "Row: " & GetRowNum([Field1]) AS RowText
FROM Table1
ORDER BY Table1.Field1, Table1.SomeDate;

Field1  Field2  RowId   RowText
James   2   1   Row: 1
James   35  2   Row: 2
James   6   3   Row: 3
James   86  4   Row: 4
James   67  5   Row: 5
James   35  6   Row: 6
Maria   4   1   Row: 1
Maria   54  2   Row: 2
Samuel  46  1   Row: 1
Samuel  32  2   Row: 2
Samuel  7   3   Row: 3
Thomas  43  1   Row: 1
Thomas  65  2   Row: 2
Thomas  5   3   Row: 3

Public StoredRowNumber As Variant
Public OldlastField As Variant

Function RowNumber(TheField) As Integer
    If OldlastField = TheField Then
        'nada
    Else
        ResetRowNum
    End If
    StoredRowNumber = StoredRowNumber + 1
    RowNumber = StoredRowNumber
    OldlastField = TheField
End Function

Function GetRowNum(TheField) As Integer
    GetRowNum = StoredRowNumber
End Function

Function ResetRowNum()
    StoredRowNumber = 0
    'OldFieldItem = Null
End Function
slavoo
  • 5,798
  • 64
  • 37
  • 39
  • Query to sort or group: – JamesDJefferys Jan 25 '16 at 18:56
  • the value returned by the function seems to update as i scroll and click through the results. Also if I add a WHERE clause on the function column `WHERE RowID = 1` I get results that show RowID =2 as well – blindguy Jan 13 '17 at 17:40
  • Very true. I was using it for a access report proc. A sort of VBA-stored procedure, and i needed the 3rd item in a large data-set. If you use it as a screen form, you would want to pull in as a temp table, or use a unique record identifier, if you need to go back to a live-production table, and make updates. But then that is a very different story, with record locks and the whole 9 yards. Maybe 9.7 yards. This is specifically needed: A report process; Very large data set; A specific row_number; no need for a view. ie SQL servers ROW_NUMBER in Access – JamesDJefferys Feb 22 '19 at 20:52
  • Still is is just a start, and considering it is VBA, the sky's the limit on expansion of the functions. The thing is, I searched multiple sites to no avail, so I had to take time to build it, i offered it to the next person to time time. – JamesDJefferys Feb 22 '19 at 21:02
  • @blindguy I solved scroll problem by caching row number already read https://stackoverflow.com/a/71580094/2958717 – doctorgu Mar 27 '22 at 11:00