可以使用想法来进一步优化这个扩展查询吗?

问题描述 投票:0回答:1

下面是基于原始“核心”查询的扩展查询。 我能够优化核心查询,但扩展查询似乎仍然可以优化。 原始核心查询

在扩展日期范围内运行时,仍然需要 15 秒,而在客户端系统上可能需要更长的时间。我可以做什么来改善结果?您是否建议使用索引临时表来存储 HomeResidentCensus 和 HomeResidentPersonalCareProvided 表(它们很大)的子集(针对选定的日期范围),以便查询不必那么辛苦,或者如果我的索引则没有必要设计得当吗?我尝试使用 CTE 存储这两个表的数据子集,但是当我尝试加入这些 CTE 时,查询实际上变得慢得多(我认为是因为您无法对 CTE 建立索引)

--ALTER PROCEDURE [dbo].[qPersonalCareNotProvided] (@FromDate datetime, @ToDate datetime, @SSNumber int) AS
DECLARE @FromDate datetime
DECLARE @ToDate datetime
DECLARE @SSNumber int
SET @FromDate = '2023-01-01'
SET @ToDate = '2023-07-03'
SET @SSNumber = -1

DECLARE @CareDates TABLE(CareDate datetime PRIMARY KEY, DOW varchar(20))
DECLARE @curDate datetime
DECLARE @curDOW varchar(20)

SET @curDate = @FromDate


WHILE DATEDIFF(day, @curDate, @ToDate + 1) > 0
BEGIN
     SET @curDOW = DATENAME(dw, @curDate)
     INSERT INTO @CareDates (CareDate, DOW) VALUES (@curDate, @curDOW)

     SET @curDate = DATEADD(day, 1, @curDate)
     PRINT DATEDIFF(day, @curDate, @ToDate)
END;


WITH personal_care AS
(
     SELECT PersonalCareID, SSNumber, ItemCode, CareSchedule, IsCurrent, StartDate
          , DATEADD(DAY, -1, (ISNULL(LEAD(StartDate,1) OVER (
              PARTITION BY SSNumber, ItemCode
              ORDER BY SSNumber, ItemCode, StartDate), '9999-12-31'))) AS EndDate
     FROM HOMEResidentPersonalCare
),
care_provided_groups AS 
(
       SELECT CareDate, SSNumber, CareTypeID, COUNT(*) AS GroupCount
       FROM HOMEResidentPersonalCareProvided
       WHERE Status = 'D'
       GROUP BY CareDate, SSNumber, CareTypeID
)

SELECT PCS.CareScheduleID, CD.CareDate, HMR.SSNumber, HMR.ResidentLastName + ', ' + HMR.ResidentFirstName + ' ' + ISNULL(ResidentMiddleInitial,'') AS ResidentName, CareTypes.Name AS CareType, 
     PCS.[Shift], HEmp.LastName + ', ' + HEmp.FirstName + ' ' + ISNULL(HEmp.MiddleInitial,'') AS EmployeeScheduled, ISNULL(HRPCP.Status,'I') AS CareStatus,
     HMRD.RoomNumber, HMRD.FloorUnit, CareSchedule, PC.StartDate, PC.EndDate,
     ISNULL((SELECT CNStatus FROM HomeResidentCensus WHERE CensusDate = CD.CareDate - 1 AND SSNumber = HMR.SSNumber),'') AS PreviousCensus
     --, PC.EndDate, PC.PersonalCareID, PCS.DayOfWeek, PCS.EmployeeID
FROM @CareDates CD
CROSS JOIN personal_care PC 
LEFT JOIN HomeTypes CareTypes ON CareTypes.ItemCode = PC.ItemCode
LEFT JOIN HomeMastResident HMR ON HMR.SSNumber = PC.SSNumber
INNER JOIN HomeResidentPersonalCareSchedule PCS ON PCS.PersonalCareID = PC.PersonalCareID AND (PCS.DayOfWeek = CD.DOW OR PCS.DayOfWeek = 'All')
LEFT JOIN HomeResidentPersonalCareProvided HRPCP ON HRPCP.CareTypeID = PC.ItemCode AND HRPCP.SSNumber = PC.SSNumber AND HRPCP.[Shift] = PCS.[Shift] AND HRPCP.CareDate = CD.CareDate
LEFT JOIN care_provided_groups CPG ON CPG.CareTypeID = PC.ItemCode AND CPG.SSNumber = PC.SSNumber AND CPG.CareDate = CD.CareDate
LEFT JOIN HomeEmployees HEmp ON HEmp.EmployeeID = PCS.EmployeeID
LEFT JOIN HomeResidentCensus HRC ON HRC.SSNumber = HMR.SSNumber AND HRC.CensusDate = CD.CareDate
LEFT JOIN HOMEMastRoomData HMRD ON HMRD.RoomID = HMR.RoomID
LEFT JOIN vAdmissionDischargeStats vADS ON vADS.SSNumber = HMR.SSNumber

WHERE CD.CareDate BETWEEN PC.StartDate AND PC.EndDate
AND (PC.SSNumber = @SSNumber OR @SSNumber = -1) 
AND (HRPCP.Status IS NULL OR HRPCP.Status <> 'D')
AND (CPG.GroupCount IS NULL OR CareTypes.ItemData2 = 0)
AND (HRC.CNStatus = '*' OR (HRC.RowID IS NULL AND HMR.Discharged = 0 AND CD.CareDate >= vADS.DOA))
ORDER BY CD.CareDate, ResidentName, CareType, [Shift]

OPTION (RECOMPILE) -- Should improve performance

这是修改后的执行计划:执行计划

尝试创建额外的索引。 还尝试将这些部分分成更易于管理的临时表,但它似乎对性能没有帮助。

sql sql-server
1个回答
0
投票

您可以使用以下方法来优化您的其中一个区块。

;WITH DateRange AS (
    SELECT @FromDate AS Date
    UNION ALL
    SELECT DATEADD(day, 1, Date)
    FROM DateRange
    WHERE Date < @ToDate
)
INSERT INTO @CareDates (CareDate, DOW)
SELECT Date, DATENAME(dw, Date)
FROM DateRange
OPTION (MAXRECURSION 0);
© www.soinside.com 2019 - 2024. All rights reserved.