1

这个查询最初来自一个 VB6 程序,它访问通过 ODBC 链接到外部数据库的 MS Access 表。运行大约需要3:30。

现在我设置了一个 SQL Server 2008 Express 框来评估我们如何迁移到更好的数据库系统。所以我为外部服务器设置了一个链接服务器(我们称之为 DWPROD),当我转换查询(将 iif 语句更改为大小写)并运行它时,我让它运行了 12 分钟,但它仍然没有完成。我是 SQL Server 的新手,所以我可以看看什么来了解什么需要这么长时间?有什么建议可以加快速度吗?推荐任何资源,以便我可以了解更多信息?与我们的查询相比,这是一个简单的查询,所以我会再次遇到这个问题。

询问:

SELECT [FISCAL_YEAR] AS FISCAL_YEAR, 
[Budgets].[dbo].[Departments].strdepentity AS ENTITY_CODE,
[Budgets].[dbo].[Departments].depdiv1 AS DIVISION_CODE, 
FINANCIAL_DEPTID AS DEPTID, 
FUND_CODE, 
[CLASS_FLD] AS CLASS_CODE, 
[PROJECT_ID], 
[PROGRAM_CODE], 
[ACCOUNT] AS ACCOUNT_CODE, 
CASE
    WHEN [ACCOUNT] in ('500020','520000','520220','520240') THEN 2
    WHEN LEFT([ACCOUNT],1)='5' THEN 1
    WHEN Left([ACCOUNT],1)='6' THEN 3
    WHEN Left([ACCOUNT],1)='7' THEN 4
    WHEN Left([ACCOUNT],1)='8' THEN 5
    ELSE 0
    END AS ACCT_GRP_CODE,
Sum([BUDGET_AMOUNT]) AS GL_BUD_AMT, 
Sum([ENCUMBRANCE_AMOUNT]) AS GL_ENC_AMT, 
Sum([EXPENDITURE_AMOUNT]) AS GL_EXP_AMT, 
CASE
    WHEN Left([CLASS_FLD],2)='12' THEN 0
    WHEN Left([CLASS_FLD],3)='113' THEN 3
    WHEN Left([CLASS_FLD],3)='112' THEN 14
    WHEN Left([CLASS_FLD],3)='115' THEN 10
    WHEN Left([CLASS_FLD],3)='116' THEN 13
    WHEN Left([CLASS_FLD],3)='117' THEN 12
    WHEN Left([CLASS_FLD],3)='118' THEN 11
    WHEN Left([CLASS_FLD],2)='13' THEN 2
    WHEN Left([CLASS_FLD],2)='14' THEN 3
    WHEN Left([CLASS_FLD],1)='4' THEN 4
    WHEN Left([CLASS_FLD],1)='6' THEN 6
    ELSE 9
    END AS FUND_SOURCE 

FROM [DWPROD]..[DISC].[PS_LEDGER_DETAIL] LEFT JOIN [Budgets].[dbo].[Departments] ON    FINANCIAL_DEPTID=[Budgets].[dbo].[Departments].deporg 
WHERE ((([BUDGET_PERIOD])='2010') And (([ACCOUNTING_PERIOD]) Between 1 And 12)) 


GROUP BY 
[FISCAL_YEAR],
[Budgets].[dbo].[Departments].strdepentity, [Budgets].[dbo].[Departments].depdiv1, 
[FINANCIAL_DEPTID],
FUND_CODE, 
[CLASS_FLD], 
[PROJECT_ID], 
[PROGRAM_CODE],
[ACCOUNT], 
CASE
    WHEN [ACCOUNT] in ('500020','520000','520220','520240') THEN 2
    WHEN LEFT([ACCOUNT],1)='5' THEN 1
    WHEN Left([ACCOUNT],1)='6' THEN 3
    WHEN Left([ACCOUNT],1)='7' THEN 4
    WHEN Left([ACCOUNT],1)='8' THEN 5
    ELSE 0
    END,
    CASE
    WHEN Left([CLASS_FLD],2)='12' THEN 0
    WHEN Left([CLASS_FLD],3)='113' THEN 3
    WHEN Left([CLASS_FLD],3)='112' THEN 14
    WHEN Left([CLASS_FLD],3)='115' THEN 10
    WHEN Left([CLASS_FLD],3)='116' THEN 13
    WHEN Left([CLASS_FLD],3)='117' THEN 12
    WHEN Left([CLASS_FLD],3)='118' THEN 11
    WHEN Left([CLASS_FLD],2)='13' THEN 2
    WHEN Left([CLASS_FLD],2)='14' THEN 3
    WHEN Left([CLASS_FLD],1)='4' THEN 4
    WHEN Left([CLASS_FLD],1)='6' THEN 6
    ELSE 9
    END
HAVING (((FISCAL_YEAR)=2010) 
AND ((FINANCIAL_DEPTID) Between '100' And '999') 
AND ((ACCOUNT) Between '500000' And '899999')) 
ORDER BY [FINANCIAL_DEPTID], [CLASS_FLD], [PROJECT_ID], [ACCOUNT]

我知道它很长。感谢您的关注。

4

1 回答 1

3

我重写了您的查询:

WITH ledger_detail AS (
      SELECT pld.fiscal_year,
             pld.financial_deptid AS DEPTID, 
             pld.fund_code,
             pld.class_fld AS CLASS_CODE, 
             pld.project_id,
             pld.program_code,
             CASE
               WHEN pld.account IN ('500020','520000','520220','520240') THEN 2
               WHEN LEFT(pld.account,1) = '5' THEN 1
               WHEN LEFT(pld.account,1) = '6' THEN 3
               WHEN LEFT(pld.account,1) = '7' THEN 4
               WHEN LEFT(pld.account,1) = '8' THEN 5
               ELSE 0
             END AS ACCT_GRP_CODE,
             pld.budget_amount,
             pld.encumbrance_amount,
             pld.expenditure_amount,
             pld.account AS ACCOUNT_CODE, 
             CASE
               WHEN LEFT(pld.class_fld, 2) ='12' THEN 0
               WHEN LEFT(pld.class_fld, 3)='113' THEN 3
               WHEN LEFT(pld.class_fld, 3)='112' THEN 14
               WHEN LEFT(pld.class_fld, 3)='115' THEN 10
               WHEN LEFT(pld.class_fld, 3)='116' THEN 13
               WHEN LEFT(pld.class_fld, 3)='117' THEN 12
               WHEN LEFT(pld.class_fld, 3)='118' THEN 11
               WHEN LEFT(pld.class_fld, 2)='13' THEN 2
               WHEN LEFT(pld.class_fld, 2)='14' THEN 3
               WHEN LEFT(pld.class_fld, 1)='4' THEN 4
               WHEN LEFT(pld.class_fld, 1)='6' THEN 6
               ELSE 9
             END AS FUND_SOURCE 
        FROM [DWPROD]..[DISC].[PS_LEDGER_DETAIL] pld
       WHERE pld.budget_period = '2010' 
         AND pld.accounting_period BETWEEN 1 AND 12
         AND pld.fiscal_year = 2010
         AND pld.financial_deptid BETWEEN '100' AND '999'
         AND pld.account BETWEEN '500000' AND '899999')
   SELECT x.fiscal_year,
          y.strdepentity AS ENTITY_CODE,
          y.depdiv1 AS DIVISION_CODE,
          x.deptid, 
          x.fund_code,
          x.class_code,
          x.project_id,
          x.program_code,
          x.acct_grp_code,
          SUM(x.budget_amount) AS GL_BUD_AMT, 
          SUM(x.encumbrance_amount) AS GL_ENC_AMT, 
          SUM(x.expenditure_amount) AS GL_EXP_AMT,
          x.account AS ACCOUNT_CODE, 
          x.fund_source
     FROM ledger_detail x
LEFT JOIN [Budgets].[dbo].[Departments] y ON y.deporg = x.financial_deptid    
 GROUP BY x.fiscal_year, y.strdepentity, y.depdiv1, x.deptid, x.fund_code, x.class_code, x.project_id, x.program_code, x.acct_grp_code
 ORDER BY x.financial_deptid, x.class_fld, x.project_id, x.account

即使您在 [DWPROD]..[DISC].[PS_LEDGER_DETAIL]account和上有索引,在它们上class_fld使用函数 ( LEFT) 也会使它们无法用于此查询。

此外,您在HAVING子句而不是WHERE子句中包含过滤条件。

更新:非 CTE 等效

   SELECT x.fiscal_year,
          y.strdepentity AS ENTITY_CODE,
          y.depdiv1 AS DIVISION_CODE,
          x.deptid, 
          x.fund_code,
          x.class_code,
          x.project_id,
          x.program_code,
          x.acct_grp_code,
          SUM(x.budget_amount) AS GL_BUD_AMT, 
          SUM(x.encumbrance_amount) AS GL_ENC_AMT, 
          SUM(x.expenditure_amount) AS GL_EXP_AMT,
          x.account AS ACCOUNT_CODE, 
          x.fund_source
     FROM (SELECT pld.fiscal_year,
                  pld.financial_deptid AS DEPTID, 
                  pld.fund_code,
                  pld.class_fld AS CLASS_CODE, 
                  pld.project_id,
                  pld.program_code,
                  CASE
                    WHEN pld.account IN ('500020','520000','520220','520240') THEN 2
                    WHEN LEFT(pld.account,1) = '5' THEN 1
                    WHEN LEFT(pld.account,1) = '6' THEN 3
                    WHEN LEFT(pld.account,1) = '7' THEN 4
                    WHEN LEFT(pld.account,1) = '8' THEN 5
                    ELSE 0
                  END AS ACCT_GRP_CODE,
                  pld.budget_amount,
                  pld.encumbrance_amount,
                  pld.expenditure_amount,
                  pld.account AS ACCOUNT_CODE, 
                  CASE
                    WHEN LEFT(pld.class_fld, 2) ='12' THEN 0
                    WHEN LEFT(pld.class_fld, 3)='113' THEN 3
                    WHEN LEFT(pld.class_fld, 3)='112' THEN 14
                    WHEN LEFT(pld.class_fld, 3)='115' THEN 10
                    WHEN LEFT(pld.class_fld, 3)='116' THEN 13
                    WHEN LEFT(pld.class_fld, 3)='117' THEN 12
                    WHEN LEFT(pld.class_fld, 3)='118' THEN 11
                    WHEN LEFT(pld.class_fld, 2)='13' THEN 2
                    WHEN LEFT(pld.class_fld, 2)='14' THEN 3
                    WHEN LEFT(pld.class_fld, 1)='4' THEN 4
                    WHEN LEFT(pld.class_fld, 1)='6' THEN 6
                    ELSE 9
                  END AS FUND_SOURCE 
             FROM [DWPROD]..[DISC].[PS_LEDGER_DETAIL] pld
            WHERE pld.budget_period = '2010' 
              AND pld.accounting_period BETWEEN 1 AND 12
              AND pld.fiscal_year = 2010
              AND pld.financial_deptid BETWEEN '100' AND '999'
              AND pld.account BETWEEN '500000' AND '899999') x
LEFT JOIN [Budgets].[dbo].[Departments] y ON y.deporg = x.financial_deptid    
 GROUP BY x.fiscal_year, y.strdepentity, y.depdiv1, x.deptid, x.fund_code, x.class_code, x.project_id, x.program_code, x.acct_grp_code
 ORDER BY x.financial_deptid, x.class_fld, x.project_id, x.account
于 2010-02-04T17:15:12.040 回答