我正在使用Microsoft Access 2010数据库从一个表中导入值并将它们附加到汇总表。
我遇到的一个问题是从select语句中找到上一个和下一个值。
这看起来如下。
JOINT JOINT AHEAD JOINT BEHIND
100103 200203
200203 300303 100103
300303 200203
我想使用SQL代码
创建它答案 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会话中运行查询,则可以使用域函数(DMin
和DMax
)而不是相关子查询。域功能经常被批评为缓慢。但是,在这种情况下,它们可能比相关子查询快得多。
更正:您无需在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