使用Microsoft Access查询结果中的行号

时间:2013-06-24 15:32:07

标签: sql ms-access

我总是在sql server中使用此查询来获取表中的行号:

SELECT *
FROM   (SELECT *,
               Row_number()
                 OVER(
                   ORDER BY [myidentitycolumn]) RowID
        FROM   mytable) sub
WHERE  rowid = 15  

现在我在Access 2010中工作,这似乎无法正常工作。在Access中是否有替换此查询?

7 个答案:

答案 0 :(得分:9)

在查询中分配行号的另一种方法是使用DCount函数。

SELECT *, DCount("[ID]","[mytable]","[ID]<=" & [ID]) AS row_id
FROM [mytable]
WHERE row_id=15

答案 1 :(得分:7)

MS-Access不支持ROW_NUMBER()。使用TOP 1:

SELECT TOP 1 *
FROM [MyTable]
ORDER BY [MyIdentityCOlumn]

如果您需要第15行 - MS-Access没有简单的内置方法。您可以使用反向嵌套排序来模拟rownumber:

SELECT TOP 1 *
FROM (
  SELECT TOP 15 *
  FROM [MyTable]
  ORDER BY [MyIdentityColumn] ) t
ORDER BY [MyIdentityColumn] DESC

答案 2 :(得分:1)

我需要每个团队得分的最佳 x 结果。

如果结果具有相同的分数,则排名无法解决此问题。 所以我需要一个recordnumber

我在Access中创建了一个VBA函数来创建一个重置ID更改的recordnumber

您必须使用recordnumber <= x查询此查询以获得每个团队的积分。

NB Access更改记录号

  1. 当您查询按记录号过滤的查询时
  2. 当您过滤掉一些结果时
  3. 更改排序顺序时
  4. 这不是我认为会发生的事情。

    通过使用临时表并在表格中保存recordnumbers和键或额外字段来解决此问题。

    SELECT ID, Points, RecordNumberOffId([ID}) AS Recordnumber
    FROM Team ORDER BY ID ASC, Points DESC;
    

    它使用3个模块级变量来记住调用

    Dim PreviousID As Long
    Dim PreviousRecordNumber As Long
    Dim TimeLastID As Date
    
    Public Function RecordNumberOffID(ID As Long) As Long 
    'ID is sortgroup identity
    'Reset if last call longer dan nn seconds in the past
    If Time() - TimeLastID > 0.0003 Then '0,000277778 = 1 second
        PreviousID = 0
        PreviousRecordNumber = 0
    End If
    If ID <> PreviousID Then
        PreviousRecordNumber = 0
        PreviousID = ID
    End If
    PreviousRecordNumber = PreviousRecordNumber + 1
    RecordNumberOffID = PreviousRecordNumber
    TimeLastID = Time()
    End Function
    

答案 3 :(得分:0)

尽管这是一个老问题,但这对我有用,但是我从未测试过它的效率...

SELECT 
    (SELECT COUNT(t1.SourceID) 
     FROM [SourceTable] t1 
     WHERE t1.SourceID<t2.SourceID) AS RowID, 
    t2.field2, 
    t2.field3, 
    t2.field4, 
    t2.field5
FROM 
    SourceTable AS t2
ORDER BY 
    t2.SourceID;

此方法的一些优点:

  • 它也不依赖于表的顺序,或者-RowID是根据其实际值和小于该值的值计算的。
  • 此方法可以应用于任何(主键)类型(例如NumberStringDate)。
  • 此方法与SQL无关,相当,或者只需要很小的改动即可。

最终想法

尽管这实际上适用于任何数据类型,但我必须强调,对于某些数据类型,它可能会产生其他问题。例如,对于字符串,请考虑:

ID     Description    ROWID
aaa    Aardvark           1
bbb    Bear               2
ccc    Canary             3

如果我要插入:bba Boar,那么Canary RowID将会改变...

ID     Description    ROWID
aaa    Aardvark           1
bbb    Bear               2
bba    Boar               3
ccc    Canary             4

答案 4 :(得分:0)

由于我是在字符串字段上按字母顺序排序,而不是按ID排序,因此Count(*)和DCOUNT() 方法对我不起作用。我的解决方案是编写一个返回行号的函数:

Option Compare Database
Option Explicit
Private Rst As Recordset

Public Function GetRowNum(ID As Long) As Long
  If Rst Is Nothing Then
    Set Rst = CurrentDb.OpenRecordset("SELECT ID FROM FileList ORDER BY RealName")
  End If
  Rst.FindFirst "ID=" & ID
  GetRowNum = Rst.AbsolutePosition + 1
' Release the Rst 1 sec after it's last use
'------------------------------------------
  SetTimer Application.hWndAccessApp, 1, 1000, AddressOf ReleaseRst  
End Function


Private Sub ReleaseRst(ByVal hWnd As LongPtr, ByVal uMsg As Long, ByVal nIDEEvent As Long, ByVal dwTime As Long)
  KillTimer Application.hWndAccessApp, 1 
  Set Rst = Nothing
End Sub

答案 5 :(得分:0)

感谢您的解决方案! DCount也帮了我大忙!

我必须使用日期列和唯一标识符的组合作为其排序部分(以及一些其他条件),所以这就是我最后要做的事情:  1)我必须检查DateColumnA是否为空,然后检查DateColumnB是否为空,然后使用DateColumnC;然后,如果多个记录具有相同的日期值,那么它们都将具有相同的id!  2)因此,我认为我将使用表的整数唯一ID,并将其加到时间上为“分钟”。这将始终提供不同的结果  3)最后,以上逻辑导致计数从0开始...所以只需加1!

SELECT 
 1+DCount("[RequestID]","[Request]","Archived=0 and ProjectPhase <> 2 and iif(isnull(DateColumnA)=true,iif(isnull(DateColumnB)=true,DateColumnC,DateColumnB),DateColumnA)+(RequestID/3600) < #" & if(isnull(DateColumnA)=true,iif(isnull(DateColumnB)=true,DateColumnC,DateColumnB),DateColumnA) + (RequestID/3600) & "#") AS RowID, 
FROM 
 Request
ORDER BY 1

希望这对您有所帮助!

答案 6 :(得分:-1)

我可能会迟到。只需在表中添加一个新字段ID,类型为AutoNumber。这将生成唯一的ID,也可以在Access中使用