我设计了一个游标来对6500名检查员运行一些统计数据,但这花费的时间太长了。游标中有许多其他选择查询,但它们运行正常,但以下选择运行速度非常慢。没有光标选择查询运行完全正常。
要求:
访问上传文件(1或2或13)的每位检查员的访问次数
表格
Inspectors: InspectorID
InspectionScope: ScopeID, InspectorID (FK)
Visits: VisitID, VisitDate ScopeID (FK)
VisitsDoc: DocID, DocType, VisitID (FK)
光标代码:
DECLARE
@curInspID int,
@DateFrom date, @DateTo date;
SELECT @DateTo = CAST(GETDATE() AS DATE)
,@DateFrom = CAST(GETDATE() - 90 AS DATE)
DECLARE
@InspectorID int,
@TotalVisits int;
DECLARE @Report TABLE (
InspectorID int,
TotalVisits int)
DECLARE curList CURSOR FOR
SELECT InspectorID FROM Inspectors ;
OPEN curList
FETCH NEXT FROM curList INTO @curInspID;
WHILE @@FETCH_STATUS = 0
BEGIN
SELECT
@curInspID = s.InspectorID
,@TotalVisits = COUNT(distinct v.visitID)
from Visits v
inner join InspectionScope s on s.ScopeID = v.ScopeID
inner join VisitDocs vd on vd.VisitID = v.VisitID
where s.InspectorID = @curInspID and vd.DocType IN (1,2,13)
and v.VisitDate BETWEEN @DateFrom and @DateTo
group by s.InspectorID
INSERT INTO @Report VALUES(@curInspID,@TotalVisits);
FETCH NEXT FROM curList INTO @curInspID;
END
CLOSE curList
DEALLOCATE curList
SELECT * FROM @Report
以下查询在同一光标内运行正常
,@TotalVisitsWithReportScore = (select COUNT(v.visitid) from visits v
inner join InspectionScope s on s.ScopeID = v.ScopeID
where v.ReportStandard not in (0,9) and v.VisitType = 1
and v.VisitDate BETWEEN @DateFrom and @DateTo
and s.InspectorID = @curInspID
)
,@TotalVisitsWith_ReportScore_RejectionFeedBack = (select COUNT(v.visitid) from visits v
inner join InspectionScope s on s.ScopeID = v.ScopeID
where v.ReportStandard not in (0,9) and v.VisitType = 1
and v.DiscrepancyType IN (2,5,6,7,8)
and v.VisitDate BETWEEN @DateFrom and @DateTo
and s.InspectorID = @curInspID
)
答案 0 :(得分:4)
此处无需使用光标 - 您可以INSERT INTO
使用SELECT
加入Inspector
表。
INSERT INTO @Report
SELECT
s.InspectorID
, COUNT(distinct v.visitID)
from Visits v
inner join InspectionScope s on s.ScopeID = v.ScopeID
inner join VisitDocs vd on vd.VisitID = v.VisitID
inner join Inspector i on s.InspectorID = i.InspectorId
where vd.DocType IN (1,2,13)
and v.VisitDate BETWEEN @DateFrom and @DateTo
group by s.InspectorID
请注意,如果该表中的结果在其他表中不存在,则可能需要对OUTER JOIN
表使用Inspector
。取决于您的数据和期望的结果。
答案 1 :(得分:1)
加速光标的最佳方法是...... 摆脱它!
在这里,你绝对不需要光标 - 简单SELECT
会做 - 并且应该基本更快!
DECLARE @Report TABLE (InspectorID int, TotalVisits int)
DECLARE curList CURSOR FOR
SELECT InspectorID FROM Inspectors ;
OPEN curList
FETCH NEXT FROM curList INTO @curInspID;
WHILE @@FETCH_STATUS = 0
BEGIN
INSERT INTO @Report (InspectorID, TotalVisits)
SELECT
i.InspectorID,
COUNT(v.visitID)
FROM
dbo.Inspectors i
INNER JOIN
dbo.InspectionScope s ON s.InspectorId = i.InspectorId
INNER JOIN
dbo.Visits v ON s.ScopeID = v.ScopeID
INNER JOIN
dbo.VisitDocs vd ON vd.VisitID = v.VisitID
WHERE
vd.DocType IN (1, 2, 13)
AND v.VisitDate BETWEEN @DateFrom AND @DateTo
GROUP BY
s.InspectorID
SELECT * FROM @Report
答案 2 :(得分:0)
不推荐使用游标。最好将数据插入临时表并向其中添加主键。
所以在你的循环中你将有一个while循环,它在你的表中循环,在你的Id中的临时表中有一个WHERE子句。
这要快得多。