【问题标题】:Fastest Way To Query SQL with Loop使用循环查询 SQL 的最快方法
【发布时间】:2018-04-27 01:09:27
【问题描述】:

我在使用 VBA 循环 SQL 查询时遇到问题,它需要很长时间才能运行。 15 分钟内循环播放 115 次。有什么办法可以减少查询时间? 这是我的代码:

    Dim Conn As New ADODB.Connection
    Dim mrs As New ADODB.Recordset
    x = 1
    DBPath = ThisWorkbook.FullName
    sconnect = "Provider=SQLOLEDB;SERVER=DWSQL\BCAPP;Database=TEST;Uid=admin;Pwd=admin;"
    Conn.Open sconnect
    Do
        If Sheets("Foil (+)").Cells(12, 12) <> "" And Sheets("Data").Cells(x, 3).Value Like "E*" Then
            sSqlSting = "SELECT *FROM [TEST].[dbo].[process_details] where pos_no = '" & Sheets("Data").Cells(x, 3) & "' and scan_type = 'Anode Foil' and status = 'OK' and returned = 'N'"
        Else
            Sheets("Data").Cells(x, 3).Value = "E" & Sheets("Data").Cells(x, 3).Value
            sSqlSting = "SELECT *FROM [TEST].[dbo].[process_details] where pos_no = '" & Sheets("Data").Cells(x, 3) & "' and scan_type = 'Anode Foil' and status = 'OK' and returned = 'N'"
        End If

        mrs.Open sSqlSting, Conn, adOpenForwardOnly
        If Sheets("Data").Cells(1, 18) = "" Then
            Sheets("Data").Cells(1, 18).CopyFromRecordset mrs
        Else
            Sheets("Data").Cells(Rows.Count, 18).End(xlUp).Offset(1, 0).CopyFromRecordset mrs
        End If
        mrs.Close
        x = x + 1
    Loop Until Sheets("Data").Cells(x, 3) = ""
    Conn.Close

【问题讨论】:

  • 如果代码有效,您应该发布到CodeReview.SE。 StackOverflow 适用于不起作用的代码。

标签: sql sql-server vba excel


【解决方案1】:
   sSqlSting = "SELECT *FROM [TEST].[dbo].[process_details] where scan_type = 'Anode Foil' and status = 'OK' and returned = 'N' and pos_no = in ('" 
enter code here

 Do
    If Sheets("Foil (+)").Cells(12, 12) <> "" And Sheets("Data").Cells(x, 3).Value Like "E*" Then
        sSqlSting = sSqlString &  Sheets("Data").Cells(x, 3) & "','"
    Else
        Sheets("Data").Cells(x, 3).Value = "E" & Sheets("Data").Cells(x, 3).Value
        sSqlSting = sSqlString &  '" & Sheets("Data").Cells(x, 3) & "','"
    End If
     x = x + 1
Loop Until Sheets("Data").Cells(x, 3) = ""

 sSqlSting = left(sSqlSting,len(sSqlsting)-1) & ")"


    mrs.Open sSqlSting, Conn, adOpenForwardOnly
    If Sheets("Data").Cells(1, 18) = "" Then
        Sheets("Data").Cells(1, 18).CopyFromRecordset mrs
    Else
        Sheets("Data").Cells(Rows.Count, 18).End(xlUp).Offset(1, 0).CopyFromRecordset mrs
    End If
    mrs.Close

【讨论】:

    【解决方案2】:

    一些想法...

    由于您的代码有效,并且您无法加快工作表中数据的实际处理速度(115 次迭代算不了什么),我猜大部分时间都花在与数据库通信上.

    在这一点上,115 次循环的 15 分钟是非同寻常的。

    如果您还没有,请确保您有一个索引:

    scan_type, status, returned, pos_no
    

    我会推荐这一切作为一个单一的索引。

    这是创可贴。您正在对同一张表进行 115 次扫描,而这只会使每次扫描更有效率 - 这就像为 115 件商品和开车而不是步行去杂货店旅行 115 次一样。

    参数化您的查询。不要传递文字,而是设置一个参数并在每个循环中发送它。

    这也是一种创可贴,更多地与礼仪而不是性能有关,尽管会有性能影响,因为您编译一个语句并执行 115 次而不是编译和执行 115 次。

    更好的是,对表进行一次扫描。执行一次查询,将结果存储在数据结构中(Dictionary 对象可能会做得很好),然后循环并应用这些结果。

    如果结果如下:

    scan_type = 'Anode Foil' and status = 'OK' and returned = 'N'
    

    足够小(

    如果它真的很大,那么首先扫描电子表格,仅针对这 115 个项目运行查询,然后再次循环遍历电子表格以分配值。将 in-list 作为参数传递可能是不可能的(顺便说一下,它在 PostgreSQL 中),因此您的动态 SQL 方法可能就足够了。

    如果列表中有数千个项目,最好的方法是将这些项目加载到临时表中,然后对表进行连接。

    【讨论】:

      猜你喜欢
      • 2017-08-19
      • 2015-11-12
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-11-07
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多