2

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

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

这看起来如下。

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

我想使用 SQL 代码创建它

4

2 回答 2

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;
于 2012-07-21T18:50:42.290 回答
1

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

如果您的源表包含少量行(例如几十行),那么速度可能不是问题。但是,如果该表包含一千行,您肯定会注意到它。如果你的JOINT字段没有被索引,性能可能会非常缓慢。

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

更正:您无需在 Access 会话中运行查询,即可使用DMin()andDMax()函数。我附上了一个 VBScript 示例,它基于我的qryDomainFunctions. 它可以正常工作并正确报告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
于 2012-07-22T01:11:11.760 回答