【问题标题】:Quicker Query from Excel thru ADO to SQL Server 2008从 Excel 到 ADO 到 SQL Server 2008 的更快查询
【发布时间】:2013-12-06 22:10:36
【问题描述】:

我开发了一些东西来帮助我们呼叫中心的一些主管提取他们自己的报告。此代码提取数据,将其放入 Excel 表格中,然后该表格用于在他们实际可以看到的工作表上进行计算。但是,当我使用 openquery 语句添加子查询时,它在 SSMS 和 Excel 中从几秒钟减慢到几分钟。使用 openquery 语句连接到链接服务器真的会减慢这么多吗?还是我的查询中的某些东西减慢了它的速度?

注意:我目前没有查看执行计划的权限,所以我无法确切地看到是什么导致了它变慢。

提前致谢!

Dim objConn As New ADODB.Connection
Dim objRecordset As New ADODB.Recordset
Dim drpPicker As DropDown
Dim strDropVal As String
Dim strSQL As String
Dim tblData As ListObject

Set tblData = ThisWorkbook.Sheets("Data").ListObjects("cs")
tblData.DataBodyRange.Rows.Delete

Set drpPicker = ThisWorkbook.Sheets("Dashboard").DropDowns("dropFis_Month")
strDropVal = Format(drpPicker.List(drpPicker.ListIndex), "mmm-yyyy")

strSQL = "" & vbNewLine
strSQL = strSQL + "select" & vbNewLine
strSQL = strSQL + "    case" & vbNewLine
strSQL = strSQL + "        when emp.intCallCenterID=10 then 'Dallas'" & vbNewLine
strSQL = strSQL + "        when emp.intCallCenterID=1 then 'Tracy'" & vbNewLine
strSQL = strSQL + "        when emp.intCallCenterID=2 then 'Ohio'" & vbNewLine
strSQL = strSQL + "    end as 'Call Center'," & vbNewLine
strSQL = strSQL + "    sup.strCsrFirstName+' '+sup.strCsrLastName as 'Supervisor'," & vbNewLine
strSQL = strSQL + "    emp.intempid as 'ID'," & vbNewLine
strSQL = strSQL + "    emp.strCsrFirstName+' '+emp.strCsrLastName as 'Name'," & vbNewLine
strSQL = strSQL + "    fis.ISODate as 'Date'," & vbNewLine
strSQL = strSQL + "    calls as 'Calls'," & vbNewLine
strSQL = strSQL + "    held_calls as 'Held Calls'," & vbNewLine
strSQL = strSQL + "    handle_time as 'Handle Time'," & vbNewLine
strSQL = strSQL + "    talk_time as 'Talk Time'," & vbNewLine
strSQL = strSQL + "    acw_time as 'ACW Time'," & vbNewLine
strSQL = strSQL + "    hold_time as 'Hold Time'," & vbNewLine
strSQL = strSQL + "    ring_time as 'Ring Time'," & vbNewLine
strSQL = strSQL + "    aux_time as 'AUX Time'," & vbNewLine
strSQL = strSQL + "    rona as 'RONA'," & vbNewLine
strSQL = strSQL + "    aux.personaltime/86400 as 'AUX-Personal'," & vbNewLine
strSQL = strSQL + "    COUNT(rls.avayadate) as 'Released Calls'," & vbNewLine
strSQL = strSQL + "    isnull(sched.sched_time,0) as 'Scheduled Time'," & vbNewLine
strSQL = strSQL + "    isnull(xep.sched_xptn,0) as 'Exceptions'," & vbNewLine
strSQL = strSQL + "    isnull(qa.qa_earned,0) as 'QA Points Earned'," & vbNewLine
strSQL = strSQL + "    isnull(qa.qa_possible,0) as 'QA Points Possible'" & vbNewLine
strSQL = strSQL + "from" & vbNewLine
strSQL = strSQL + "    (" & vbNewLine
strSQL = strSQL + "    select" & vbNewLine
strSQL = strSQL + "        sum(CallsHandled) as 'calls'," & vbNewLine
strSQL = strSQL + "        SUM(heldcalls) as 'held_calls'," & vbNewLine
strSQL = strSQL + "        sum(acdtime+acwtime+holdtime) as 'handle_time'," & vbNewLine
strSQL = strSQL + "        sum(ACDTime) as 'talk_time'," & vbNewLine
strSQL = strSQL + "        sum(ACWTime) as 'acw_time'," & vbNewLine
strSQL = strSQL + "        sum(HoldTime) as 'hold_time'," & vbNewLine
strSQL = strSQL + "        sum(ringtime) as 'ring_time'," & vbNewLine
strSQL = strSQL + "        sum(auxtime) as 'aux_time'," & vbNewLine
strSQL = strSQL + "        sum(redirectnoans) as 'rona'," & vbNewLine
strSQL = strSQL + "        employee_id," & vbNewLine
strSQL = strSQL + "        AvayaDate" & vbNewLine
strSQL = strSQL + "    from" & vbNewLine
strSQL = strSQL + "        reporting.dbo.phones" & vbNewLine
strSQL = strSQL + "    Group by" & vbNewLine
strSQL = strSQL + "        employee_id," & vbNewLine
strSQL = strSQL + "        AvayaDate" & vbNewLine
strSQL = strSQL + "    ) fone" & vbNewLine
strSQL = strSQL + "    join ccat.dbo.tblEmployees emp on emp.intEmpID=fone.employee_id" & vbNewLine
strSQL = strSQL + "    join ccat.dbo.tblEmployees sup on sup.id=emp.intSupervisorID" & vbNewLine
strSQL = strSQL + "    join FiscalCal fis on Fis.isodate=fone.AvayaDate" & vbNewLine
strSQL = strSQL + "    left join phones_auxes aux on aux.employee_id=emp.intEmpID and aux.AvayaDate=fis.ISODate" & vbNewLine
strSQL = strSQL + "    left outer join reporting.dbo.agent_releases rls on rls.avayadate=Fis.ISODate and rls.employee_id=emp.intEmpID" & vbNewLine
strSQL = strSQL + "    left outer join (" & vbNewLine
strSQL = strSQL + "    select" & vbNewLine
strSQL = strSQL + "        s.id as 'sched_id'," & vbNewLine
strSQL = strSQL + "        s.employee_id as 'sched_emp'," & vbNewLine
strSQL = strSQL + "        s.schedule_date as 'sched_date'," & vbNewLine
strSQL = strSQL + "        DATEDIFF(ss,s.start_time,s.end_time) as 'sched_time'" & vbNewLine
strSQL = strSQL + "    from" & vbNewLine
strSQL = strSQL + "        reporting.dbo.Schedules s" & vbNewLine
strSQL = strSQL + "    Group by" & vbNewLine
strSQL = strSQL + "        s.schedule_date," & vbNewLine
strSQL = strSQL + "        s.employee_id," & vbNewLine
strSQL = strSQL + "        s.start_time," & vbNewLine
strSQL = strSQL + "        s.end_time," & vbNewLine
strSQL = strSQL + "        s.ID" & vbNewLine
strSQL = strSQL + "    ) sched on sched.sched_date=fis.ISODate and sched.sched_emp=fone.employee_id" & vbNewLine
strSQL = strSQL + "    left outer join (" & vbNewLine
strSQL = strSQL + "    select" & vbNewLine
strSQL = strSQL + "        schedule_id as 'sched_id'," & vbNewLine
strSQL = strSQL + "        SUM(duration)as 'sched_xptn'" & vbNewLine
strSQL = strSQL + "    from" & vbNewLine
strSQL = strSQL + "        reporting.dbo.violations" & vbNewLine
strSQL = strSQL + "    where" & vbNewLine
strSQL = strSQL + "        isapproved = 0" & vbNewLine
strSQL = strSQL + "    Group by" & vbNewLine
strSQL = strSQL + "        schedule_id" & vbNewLine
strSQL = strSQL + "    ) xep on xep.sched_id=sched.sched_id" & vbNewLine
strSQL = strSQL + "    left outer join (" & vbNewLine
strSQL = strSQL + "    select" & vbNewLine
strSQL = strSQL + "        cast(cast(eval.eval_datetime as date) as datetime) as 'qa_date'," & vbNewLine
strSQL = strSQL + "        prsn.personnel_id as 'qa_emp'," & vbNewLine
strSQL = strSQL + "        sum(eval.form_total) as 'qa_earned'," & vbNewLine
strSQL = strSQL + "        sum(eval.form_possible) as 'qa_possible'" & vbNewLine
strSQL = strSQL + "    from" & vbNewLine
strSQL = strSQL + "        openquery ( jeffqms ,'select * from witness.dbo.evaluations' ) eval" & vbNewLine
strSQL = strSQL + "        join openquery ( jeffqms ,'select * from witness.dbo.person' ) prsn ON eval.person_pk = prsn.person_pk" & vbNewLine
strSQL = strSQL + "    where" & vbNewLine
strSQL = strSQL + "        prsn.personnel_id is not null" & vbNewLine
strSQL = strSQL + "        and prsn.login_name is not null" & vbNewLine
strSQL = strSQL + "        and eval.calibration != 'T'" & vbNewLine
strSQL = strSQL + "        and prsn.personnel_id not like 'TestUser'" & vbNewLine
strSQL = strSQL + "        and prsn.personnel_id not like 'IT'" & vbNewLine
strSQL = strSQL + "    Group by" & vbNewLine
strSQL = strSQL + "        personnel_id" & vbNewLine
strSQL = strSQL + "        ,cast(cast(eval.eval_datetime as date) as datetime)) qa on qa.qa_date=fis.ISODate and qa.qa_emp=emp.intEmpID" & vbNewLine
strSQL = strSQL + "where" & vbNewLine
strSQL = strSQL + "    (emp.intCallCenterID=10 or emp.intCallCenterID=1 or emp.intCallCenterID=2)" & vbNewLine
strSQL = strSQL + "    and fis.FIS_MM_YYYY='" & strDropVal & "'" & vbNewLine
strSQL = strSQL + "    and emp.strStatus='active'" & vbNewLine
strSQL = strSQL + "    and (emp.intcscdeptid=14 or emp.intcscdeptid=19) " & vbNewLine
strSQL = strSQL + "Group by" & vbNewLine
strSQL = strSQL + "    Fis.ISODate," & vbNewLine
strSQL = strSQL + "    emp.intEmpID," & vbNewLine
strSQL = strSQL + "    emp.strCsrFirstName," & vbNewLine
strSQL = strSQL + "    emp.strCsrLastName," & vbNewLine
strSQL = strSQL + "    sup.strCsrFirstName," & vbNewLine
strSQL = strSQL + "    sup.strCsrLastName," & vbNewLine
strSQL = strSQL + "    emp.intCallCenterID," & vbNewLine
strSQL = strSQL + "    fone.calls," & vbNewLine
strSQL = strSQL + "    fone.held_calls," & vbNewLine
strSQL = strSQL + "    fone.handle_time," & vbNewLine
strSQL = strSQL + "    fone.talk_time," & vbNewLine
strSQL = strSQL + "    fone.acw_time," & vbNewLine
strSQL = strSQL + "    fone.hold_time," & vbNewLine
strSQL = strSQL + "    fone.ring_time," & vbNewLine
strSQL = strSQL + "    fone.aux_time," & vbNewLine
strSQL = strSQL + "    fone.rona," & vbNewLine
strSQL = strSQL + "    aux.personaltime," & vbNewLine
strSQL = strSQL + "    sched.sched_time," & vbNewLine
strSQL = strSQL + "    xep.sched_xptn," & vbNewLine
strSQL = strSQL + "    qa.qa_earned," & vbNewLine
strSQL = strSQL + "    qa.qa_possible" & vbNewLine
strSQL = strSQL + "Order by" & vbNewLine
strSQL = strSQL + "    [Call Center]," & vbNewLine
strSQL = strSQL + "    Supervisor," & vbNewLine
strSQL = strSQL + "    Name," & vbNewLine
strSQL = strSQL + "    fis.ISODate"

objConn.Open "Provider=SQLOLEDB.1;Initial Catalog=database_name;Data Source=server_name;UID=user_name;PWD=password"

With objRecordset
    .ActiveConnection = objConn
    .Open Source:=strSQL
End With

ThisWorkbook.Sheets("Data").Range("A2").CopyFromRecordset objRecordset

objRecordset.Close
Set objRecordset = Nothing
objConn.Close
Set objConn = Nothing

【问题讨论】:

    标签: sql-server excel vba ado


    【解决方案1】:

    您真的需要来自 witness.dbo.evaluations 的每一列 (*) 吗?

    我会在您的子查询 Where 子句 inside 引号内的 OpenQuery select 语句中添加一些详细信息,并将其限制为所需的列。这将导致在 jeffqms 服务器上完成更多工作,并减少通过网络返回的数据。

    例如在您上面的代码中

    select" & vbNewLine
    strSQL = strSQL + "        cast(cast(eval.eval_datetime as date) as datetime) as 'qa_date'," & vbNewLine
    strSQL = strSQL + "        prsn.personnel_id as 'qa_emp'," & vbNewLine
    strSQL = strSQL + "        sum(eval.form_total) as 'qa_earned'," & vbNewLine
    strSQL = strSQL + "        sum(eval.form_possible) as 'qa_possible'" & vbNewLine
    strSQL = strSQL + "    from" & vbNewLine
    strSQL = strSQL + "        openquery ( jeffqms ,'select * from witness.dbo.evaluations' ) eval" & vbNewLine
    strSQL = strSQL + "        join openquery ( jeffqms ,'select * from witness.dbo.person' ) prsn ON eval.person_pk = prsn.person_pk" & vbNewLine
    strSQL = strSQL + "    where" & vbNewLine
    strSQL = strSQL + "        prsn.personnel_id is not null" & vbNewLine
    strSQL = strSQL + "        and prsn.login_name is not null" & vbNewLine
    strSQL = strSQL + "        and eval.calibration != 'T'" & vbNewLine
    strSQL = strSQL + "        and prsn.personnel_id not like 'TestUser'" & vbNewLine
    strSQL = strSQL + "        and prsn.personnel_id not like 'IT'" & vbNewLine
    

    “eval.calibration != 'T'”、“prsn.personnel_id not like 'TestUser'”和“prsn.personnel_id not like 'IT'”可以放在 openquery 'select' 语句中以提前限制行。

    另外,为什么不将 eval 和 person 之间的整个连接放在一个 openquery 语句中,以节省两次访问 jeffqms 的时间。

    openquery ( jeffqms ,'select column, column, column from witness.dbo.evaluations join witness.dbo.person where blah blah' )
    

    我总是发现在少数情况下我不得不使用 openquery,首先在远程服务器上做尽可能多的事情。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2013-05-11
      • 2013-09-01
      • 2013-10-17
      • 2011-05-01
      • 1970-01-01
      • 1970-01-01
      • 2014-04-15
      相关资源
      最近更新 更多