Excel 中 ADODB 的限制是什么 - 奇怪的结果

问题描述 投票:0回答:1

潜伏已久,第一次发海报。 感谢您之前的所有帮助 - 非常感谢,我学到了很多!

我有一个包含 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 时,您确实需要括号来确保逻辑符合您的预期......

sql excel vba adodb
1个回答
0
投票

应该是

...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 问题。

© www.soinside.com 2019 - 2024. All rights reserved.