使用SQL查找访问中的上一个和下一个值

时间:2012-07-21 18:37:25

标签: sql ms-access

我正在使用Microsoft Access 2010数据库从一个表中导入值并将它们附加到汇总表。

我遇到的一个问题是从select语句中找到上一个和下一个值。

这看起来如下。

JOINT          JOINT AHEAD             JOINT BEHIND
100103           200203
200203           300303                  100103
300303                                   200203

我想使用SQL代码

创建它

2 个答案:

答案 0 :(得分:1)

怎么样:

SELECT a.JOINT, 
      (SELECT TOP 1 Joint 
       FROM Joint b 
       WHERE b.JOINT>a.JOINT 
       ORDER BY Joint) AS Ahead,
      (SELECT TOP 1 Joint 
       FROM Joint b 
       WHERE b.JOINT<a.JOINT 
       ORDER BY Joint DESC) AS Behind
FROM Joint AS a;

答案 1 :(得分:1)

在考虑相关子查询时要小心。它们可能非常慢。如果您构建一个包含两个相关子查询的查询,您将放大该问题。

如果您的源表包含少量行(比如几十行),那么缓慢可能不是问题。但是,如果表中包含一千行,您肯定会注意到它。如果您的JOINT字段未编入索引,则性能可能会非常缓慢。

如果要在Access会话中运行查询,则可以使用域函数(DMinDMax)而不是相关子查询。域功能经常被批评为缓慢。但是,在这种情况下,它们可能比相关子查询快得多。

更正:您无需在Access会话中运行查询,以便能够使用DMin()DMax()功能。我附加了一个VBScript示例,该示例基于我的qryDomainFunctions打开ADO Recordset。它可以正常工作并正确报告RecordCount: 1000

我创建了一个表joints,其中一个长整数字段joint作为主键,并添加了1000行。然后我创建了这两个查询:

<强> qryCorrelatedSubqueries

SELECT
    a.joint,
    (SELECT TOP 1 joint 
    FROM joints b 
    WHERE b.joint>a.joint 
    ORDER BY joint) AS Ahead,
    (SELECT TOP 1 joint 
    FROM joints b 
    WHERE b.joint<a.joint 
    ORDER BY joint DESC) AS Behind
FROM joints AS a;

<强> qryDomainFunctions

SELECT
    j.joint,
    DMin("joint","joints","joint > " & [joint]) AS joint_ahead,
    DMax("joint","joints","joint < " & [joint]) AS joint_behind
FROM joints AS j;

以下是立即窗口中的成绩单,我使用下面的QueryDuration函数比较了这两个查询的速度。该函数以毫秒为单位返回持续时间。

? QueryDuration("qryDomainFunctions")
 0 

? QueryDuration("qryCorrelatedSubqueries")
 889

请注意,这两个查询都受益于joints字段上的索引。当我删除索引时,压缩数据库,并重新运行测试,我得到了这些结果:

? QueryDuration("qryDomainFunctions")
 16 

? QueryDuration("qryCorrelatedSubqueries")
 4570

这是包含我使用的代码的模块。 QueryDuration绝不是绩效衡量的最后一句话。但是,它足以让我们大致了解这两个查询的相对速度。

Option Compare Database
Option Explicit

Private Declare Function apiGetTickCount Lib "kernel32" _
 Alias "GetTickCount" () As Long

Public Function QueryDuration(ByVal pQueryName As String) As Long
    Dim db As DAO.Database
    Dim lngStart As Long
    Dim lngDone As Long
    Dim rs As DAO.Recordset

    Set db = CurrentDb()
    lngStart = apiGetTickCount() ' milliseconds '
    Set rs = db.OpenRecordset(pQueryName, dbOpenSnapshot)
    If Not rs.EOF Then
        rs.MoveLast
    End If
    lngDone = apiGetTickCount()
    rs.Close
    Set rs = Nothing
    Set db = Nothing
    QueryDuration = lngDone - lngStart
End Function

<强> DomainFunctionsQuery.vbs

Option Explicit
Dim cn, rs
Set cn = CreateObject("ADODB.Connection")
cn.Open "Provider=Microsoft.Jet.OLEDB.4.0;" & _
    "Data Source='database1.mdb'"
Set rs = CreateObject("ADODB.Recordset")
rs.CursorLocation = 3 ' adUseClient '
rs.Open "qryDomainFunctions", cn, 3 ' adOpenStatic = 3 '
WScript.Echo "RecordCount: " & rs.RecordCount
rs.Close
Set rs = Nothing
cn.Close
Set cn = Nothing