0

如何使这个 SQL 查询更高效?下面显示的 CteFinal 代码是我的查询的一部分,我的查询最多需要 6 分钟。cteMonth 如下所示。cteDetail 是另一个直接从数据库中提取信息的 cte,运行时间不到一秒。

CteFinal 所做的是创建缺少的会计期间行,同时包括 f.FiscalPeriod=0 行中的一些列数据。

我不能添加、删除或更改表上的任何索引,因为这是一个 ERP 数据库,我不允许进行这些类型的更改。

CteFinal:

SELECT      Account,Month, CONVERT(DATETIME, CAST(@Year as varchar(4)) + '-' + CAST(Month as VARCHAR(2)) + '-' + '01', 102) JEDate
        ,accountdesc,'' Description,'' JournalCode,NULL JournalNum,NULL JournalLine
        ,'' LegalNumber,'' CurrencyCode,0.00 DebitAmount,0.00 CreditAmount,fiscalcalendarid,company,bookid,SegValue2,SegValue1,SegValue3,SegValue4

FROM        cteDetail f
        CROSS JOIN cteMonths m

WHERE       f.FiscalPeriod=0 and not exists(select * from cteDetailADDCreatedZero x where x.Account=f.Account and x.FiscalPeriod=Month)

CteMonth:

cteMonths (Month) AS(
select 0 as Month
UNION select 1 as Month
UNION select 2 as Month
UNION select 3 as Month
UNION select 4 as Month
UNION select 5 as Month
UNION select 6 as Month
UNION select 7 as Month
UNION select 8 as Month
UNION select 9 as Month
UNION select 10 as Month
UNION select 11 as Month
UNION select 12 as Month)

谢谢!

4

2 回答 2

2

这是一种更有效的方法来生成给定年份的 12 个月(如果您有自己的 Numbers 表,效率会更高):

DECLARE @year INT = 2013;

;WITH cteMonths([Month],AsDate) AS
(
  SELECT n-1,DATEADD(YEAR, @Year-1900, DATEADD(MONTH,n-1,0)) FROM (
    SELECT TOP (13) RANK() OVER (ORDER BY [object_id]) FROM sys.all_objects
  ) AS c(n)
)
SELECT [Month], AsDate FROM cteMonths;

所以现在,你可以说:

;WITH cteMonths([Month],AsDate) AS
(
  SELECT n,DATEADD(YEAR, @Year-1900, DATEADD(MONTH,n-1,0)) FROM (
    SELECT TOP (13) RANK() OVER (ORDER BY [object_id]) FROM sys.all_objects
  ) AS c(n)
), 
cteDetail AS 
(
  ...no idea what is here...
),
cteDetailADDCreatedZero AS
(
  ...no idea what is here...
)
SELECT f.Account, m.[Month], JEDate = m.AsDate, f.accountdesc, Description = '',
  JournalCode = '', JournalNum = NULL, JournalLine = NULL, LegalNumber = '', 
  CurrencyCode = '', DebitAmount = 0.00, CreditAmount = 0.00, f.fiscalcalendarid, 
  f.company, f.bookid, f.SegValue2, f.SegValue1, f.SegValue3, f.SegValue4
FROM cteMonths AS m
LEFT OUTER JOIN cteDetail AS f
ON ... some clause I am not clear on ...  
WHERE f.FiscalPeriod = 0 
AND NOT EXISTS 
(
  SELECT 1 FROM cteDetailADDCreatedZero AS x 
  WHERE x.Account = f.Account 
  AND x.FiscalPeriod = m.[Month]
);

我怀疑这不会解决您的问题:这很可能会强制对中提到的任何表或两者都进行整个表cteDetail扫描cteDetailADDCreatedZero。您应该检查此查询的实际执行计划,看看是否有任何扫描或其他昂贵的操作可以引导您更好地建立索引。也可能只是您将一堆低效的 CTE 堆叠在一起 - 除非您展示所有内容,否则我们无法真正提供帮助。CTE 就像视图 - 如果您开始将它们堆叠在一起,您实际上会限制优化器为您生成有效计划的能力。在某些时候,它会把手举到空中……

于 2013-10-08T21:55:11.117 回答
0

一种可能性是物理化 SQL 视图(如果查询是视图)。有时具有复杂查询的视图很慢。

于 2021-01-11T11:03:14.813 回答