潜伏已久,第一次发海报。 感谢您之前的所有帮助 - 非常感谢,我学到了很多!
我有一个包含 107,141 条记录的 Excel 工作表。 作为参考,我使用此页面中的基本代码: https://stackoverflow.com/questions/57701533/using-excel-vba-how-do-i-limit-the-results-of-a-query-using-adodb-connection
Public Function RecordSetFromSheet(sheetName As String)
Dim rst As New ADODB.Recordset
Dim cnx As New ADODB.Connection
Dim cmd As New ADODB.Command
'setup the connection
'[HDR=Yes] means the Field names are in the first row
With cnx
.Provider = "Microsoft.Jet.OLEDB.4.0"
.ConnectionString = "Data Source='" & ThisWorkbook.FullName & "'; " & "Extended Properties='Excel 8.0;HDR=Yes;IMEX=1'"
.Open
End With
str_SQL = "SELECT * From [" & sheetName & "$]" & _
"WHERE [Profession] = 'Veterinary Medicine' " & _
"AND [Type] = 'Veterinarian' Or [Type] = 'Veterinarian Cln Ac Ltd' Or [Type] = 'Veterinarian Ed Ltd' Or [Type] = 'Veterinarian Nonaprv Prgm Ltd' " & _
"AND [County] = 'Livingston' Or [County] = 'Macomb' Or [County] = 'Monroe' Or [County] = 'Oakland' Or [County] = 'Washtenaw' Or [County] = 'Wayne'"
'setup the command
Set cmd.ActiveConnection = cnx
cmd.CommandType = adCmdText
' cmd.CommandText = "SELECT * FROM [" & sheetName & "$]"
cmd.CommandText = str_SQL
rst.CursorLocation = adUseClient
rst.CursorType = adOpenDynamic
rst.LockType = adLockOptimistic
'open the connection
rst.Open cmd
'disconnect the recordset
Set rst.ActiveConnection = Nothing
'cleanup
If CBool(cmd.State And adStateOpen) = True Then
Set cmd = Nothing
End If
If CBool(cnx.State And adStateOpen) = True Then cnx.Close
Set cnx = Nothing
'"return" the recordset object
Set RecordSetFromSheet = rst
End Function
Public Sub Test()
Dim rstData As ADODB.Recordset
Set rstData = RecordSetFromSheet("Sheet2")
rstData.MoveFirst
rstData.MoveLast
MsgBox rstData.RecordCount
rstData.Filter = "County = 'Macomb'"
rstData.MoveFirst
rstData.MoveLast
MsgBox rstData.RecordCount
rstData.Close
Set rstData = Nothing
End Sub
创建对象和记录集时没有错误。
但是,由于坏运气不好,我需要的记录(至少在最初)都位于数据的底部。
我将其描述为运气不好,因为当我使用以下 SQL 时:
str_SQL = "SELECT * From [" & sheetName & "$]"
我只得到上面的 41,604 条记录。
ADODB 是否有一些内置限制? 这是系统资源限制吗? 如果是这样,在不添加更多内存的情况下,是否可以应用任何设置来获取所有(或至少更多)记录?
但是等等,还有更多...
为了执行更多测试并希望能够解决此问题,我将底部 14,592 条记录复制到另一个工作表中(还更新了代码中的工作表名称引用)。 现在,当我重新运行上述 SQL 时,我得到了正确的记录数:14,592。 但我需要进一步缩小记录范围,因此我添加了更多 SQL,如下所示:
str_SQL = "SELECT * From [" & sheetName & "$]" & _
"WHERE [Profession] = 'Veterinary Medicine' " & _
"AND [Type] = 'Veterinarian' Or [Type] = 'Veterinarian Cln Ac Ltd' Or [Type] = 'Veterinarian Ed Ltd' Or [Type] = 'Veterinarian Nonaprv Prgm Ltd'"
实际上,为了节省空间,从技术上讲,我首先添加了最初的
WHERE
子句,当记录计数正确时,我添加了以下 AND
子句。
此查询返回正确的记录数,4,584。
但是事情又变得奇怪了...... 如果我运行下面的 SQL:
str_SQL = "SELECT * From [" & sheetName & "$]" & _
"WHERE [Profession] = 'Veterinary Medicine' " & _
"AND [Type] = 'Veterinarian' Or [Type] = 'Veterinarian Cln Ac Ltd' Or [Type] = 'Veterinarian Ed Ltd' Or [Type] = 'Veterinarian Nonaprv Prgm Ltd' " & _
"AND [County] = 'Livingston' Or [County] = 'Macomb' Or [County] = 'Monroe' Or [County] = 'Oakland' Or [County] = 'Washtenaw' Or [County] = 'Wayne'"
我得到8,741记录!!!
作为进一步的测试,如果我在生成的记录集上使用以下行:
rstData.Filter = "County = 'Macomb'"
我得到 1,099 条记录,而不是正确的记录数 184 条。
然而,很明显 .Filter
正在过滤记录集,尽管没有达到正确的记录计数。
最有可能的是,.Filter
导致错误的记录计数,因为初始记录集的记录太多。我知道这是真的,因为如果我在具有正确记录数的最后一个 SQL 化身上使用过滤器 rstData.Filter = "County = 'Macomb'"
,过滤器会按预期生成 184 条记录。
但是最后一条 SQL 发生了什么?
结果记录集如何比不包含最后一个 AND
子句的 SQL 获得*更多*记录?
我的 SQL 有问题还是我遗漏了一些重要的东西?
[挠头开始]
我在这里缺少什么吗?
在 SQL 中混合 AND 和 OR 时,您确实需要括号来确保逻辑符合您的预期......
应该是
...AND (A or B or c)
AND (C or D or E)
这个(例如):
AND [County] = 'Livingston' Or [County] = 'Macomb' Or [County] = 'Monroe' Or [County] = 'Oakland' Or [County] = 'Washtenaw' Or [County] = 'Wayne'"
也可以写成:
AND [County] IN ('Livingston','Macomb','Monroe','Oakland','Washtenaw', 'Wayne')
...这也可以帮助解决 AND/OR 问题。