Row_Number() в операторе выбора Access

Я считаю, что подобные вопросы задавались, но я не могу найти решение, которое работает для меня.

У меня есть база данных, которую я использую для сортировки оцифрованных книг и их страниц, и я пытаюсь отсортировать несколько тысяч страниц, содержащих карты. Из двух таблиц, которые я использую, первая перечисляет все страницы в книге и порядок их появления в книге, у нее есть три столбца (bookID, pageOrder, pageID), каждая страница имеет свою собственную строку. Во второй таблице перечислены все места (на карте), которые встречаются на каждой странице, в ней есть два столбца (pageID, placeID), если на одной странице есть несколько мест, то для каждого места в таблицу добавляется новая строка.

Что мне нужно сделать, так это создать оператор select, который присваивает каждой комбинации pageID/placeID уникальный номер, но числа должны идти в том порядке, в котором они появляются в книге. В SQL Server я бы сделал так:

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

К сожалению, я застрял с помощью Access. В идеале я хотел бы сделать это (если возможно) с помощью одного оператора SQL, аналогичного приведенному выше, но я также попробовал бы это с помощью VBA.

Любая помощь приветствуется.


person user2770656    schedule 12.09.2013    source источник
comment
Проверьте это решение (см. решение 2 относительно DCount()) stackoverflow.com/questions/17279320/   -  person cha    schedule 12.09.2013


Ответы (3)


Это запрос, который вы хотите:

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;

Вы можете получить тот же результат, используя коррелированный подзапрос. Сложнее и дороже, но возможно:

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;

Это предполагает, что комбинация bookId, pageOrder, placeId` уникальна.

person Gordon Linoff    schedule 12.09.2013

Я знаю, что это старый вопрос, но это был лучший поиск, и я не видел других решений в Интернете, поэтому надеюсь, что это поможет другим.

Мое решение работает для любого набора данных независимо от того, имеет он уникальный идентификатор или нет.

Добавьте следующий код VBA в модуль:

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

А теперь пример запроса:

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

Вы можете добавить любой «ORDER BY» или даже «GROUP BY», если хотите. Вы можете использовать любое поле, которое будет в выходных данных запроса, в качестве входных данных для RowNum и GetRowNum. Важно отметить, что используйте RowNum только в первый раз, когда вам нужен номер строки, и используйте GetRowNum каждый раз после этого. Это делается для того, чтобы одна строка не увеличивала значение счетчика более одного раза.

Последнее, что вам нужно сделать, это создать макрос, который запускает ResetRowNum, и запускать его после каждого запроса, который вы используете с этим методом, или, если вы выполняете серию запросов через макрос или VBA, обязательно запускайте ResetRowNum после каждого запроса. который использует эти функции.

Также избегайте просмотра таблицы, так как кажется, что при прокрутке формулы постоянно пересчитываются, что приводит к постоянному увеличению чисел.

person Aehetag    schedule 28.08.2014
comment
Ваша функция RowNum может принимать второй необязательный логический параметр, когда строка не должна быть расширена. Это устранило бы необходимость в функции GetRowNum. - person Zev Spitz; 03.03.2016

Запрос для сортировки и/или группировки

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
person JamesDJefferys    schedule 25.01.2016
comment
Запрос для сортировки или группировки: - person JamesDJefferys; 25.01.2016
comment
значение, возвращаемое функцией, кажется, обновляется, когда я прокручиваю и просматриваю результаты. Также, если я добавлю предложение WHERE в столбец функции WHERE RowID = 1, я также получу результаты, которые также показывают RowID = 2. - person blindguy; 13.01.2017
comment
Очень верно. Я использовал его для процедуры отчета о доступе. Что-то вроде хранимой процедуры VBA, и мне нужен был третий элемент в большом наборе данных. Если вы используете его в качестве экранной формы, вы захотите использовать временную таблицу или использовать уникальный идентификатор записи, если вам нужно вернуться к рабочей таблице и внести обновления. Но тогда это совсем другая история, с рекордными замками и целыми 9 ярдами. Может быть, 9,7 ярда. Это особенно необходимо: процесс отчетности; Очень большой набор данных; Конкретный row_number; вид не нужен. т.е. серверы SQL ROW_NUMBER в Access - person JamesDJefferys; 22.02.2019
comment
Тем не менее, это только начало, и, учитывая, что это VBA, нет предела расширению функций. Дело в том, что я искал несколько сайтов безрезультатно, поэтому мне пришлось потратить время на его создание, я предложил его следующему человеку время от времени. - person JamesDJefferys; 23.02.2019