执行当前查询需要1:16分钟。这太长了。以下是我的查询看起来像atm:
SELECT
[plugin.tickets].[Ticket].Id,
[plugin.tickets].[Ticket].Title,
[plugin.tickets].[Ticket].Created,
[plugin.tickets].[Ticket].StartProgress,
[dbo].[worktime]([plugin.tickets].[Ticket].Created, GetDate()) AS OpenstaandeTijdInUren,
[plugin.tickets].[Ticket].firstresponse,
DATEDIFF(HOUR, [plugin.tickets].[Ticket].Created, [plugin.tickets].[Ticket].FirstResponse) AS ReactietijdInUren,
[plugin.tickets].[Ticket].Status,
[plugin.tickets].[Ticket].Priority,
DATEDIFF (MINUTE, [plugin.tickets].[Ticket].Created, [plugin.tickets].[Ticket].EndProgress) as OplostijdTicketInUren
FROM [plugin.tickets].[Ticket]
WHERE [dbo].[worktime]([plugin.tickets].[Ticket].Created, GetDate()) >= 1
AND ([plugin.tickets].[Ticket].status <= 2)
ORDER BY [plugin.tickets].[Ticket].id
在查询中有一个我使用的功能,我做了。该函数计算两个日期之间的小时差异。为了计算不包括假期的时间,我制作了一张表格,其中包含了即将到来的10年的假期。这很可能就是为什么查询执行需要这么长时间,因为对于每一行,它检查日期包含与假日表相同的日期。但我不确定这个问题的解决方案是什么?
这是我的功能:
ALTER FUNCTION [dbo].[WorkTime]
(@StartDate DATETIME, @FinishDate DATETIME)
RETURNS BIGINT
AS
BEGIN
DECLARE @Temp BIGINT
SET @Temp = 0
DECLARE @FirstDay DATE
SET @FirstDay = CONVERT(DATE, @StartDate, 112)
DECLARE @LastDay DATE
SET @LastDay = CONVERT(DATE, @FinishDate, 112)
DECLARE @StartTime TIME
SET @StartTime = CONVERT(TIME, @StartDate)
DECLARE @FinishTime TIME
SET @FinishTime = CONVERT(TIME, @FinishDate)
DECLARE @WorkStart TIME
SET @WorkStart = '08:00'
DECLARE @WorkFinish TIME
SET @WorkFinish = '18:00'
DECLARE @DailyWorkTime BIGINT
SET @DailyWorkTime = DATEDIFF(HOUR, @WorkStart, @WorkFinish)
IF (@StartTime<@WorkStart)
BEGIN
SET @StartTime = @WorkStart
END
IF (@FinishTime>@WorkFinish)
BEGIN
SET @FinishTime=@WorkFinish
END
IF (@FinishTime<@WorkStart)
BEGIN
SET @FinishTime=@WorkStart
END
IF (@StartTime>@WorkFinish)
BEGIN
SET @StartTime = @WorkFinish
END
DECLARE @CurrentDate DATE
SET @CurrentDate = @FirstDay
DECLARE @LastDate DATE
SET @LastDate = @LastDay
WHILE(@CurrentDate<=@LastDate)
BEGIN
IF
(DATEPART(dw, @CurrentDate)!=1 AND DATEPART(dw, @CurrentDate)!=7)
AND @CurrentDate NOT IN
(SELECT Datum_feestdag FROM Feestdagen)
BEGIN
IF (@CurrentDate!=@FirstDay) AND (@CurrentDate!=@LastDay)
BEGIN
SET @Temp = @Temp + @DailyWorkTime
END
--IF it starts at startdate and it finishes not this date find diff between work finish and start as hours
ELSE IF (@CurrentDate=@FirstDay) AND (@CurrentDate!=@LastDay)
BEGIN
SET @Temp = @Temp + DATEDIFF(HOUR, @StartTime, @WorkFinish)
END
ELSE IF (@CurrentDate!=@FirstDay) AND (@CurrentDate=@LastDay)
BEGIN
SET @Temp = @Temp + DATEDIFF(HOUR, @WorkStart, @FinishTime)
END
--IF it starts and finishes in the same date
ELSE IF (@CurrentDate=@FirstDay) AND (@CurrentDate=@LastDay)
BEGIN
SET @Temp = DATEDIFF(HOUR, @StartTime, @FinishTime)
END
END
SET @CurrentDate = DATEADD(day, 1, @CurrentDate)
END
-- Return the result of the function
IF @Temp < 0
BEGIN
SET @Temp = 0
END
RETURN @Temp
END
如何在不使用查询中的函数的情况下运行查询?我已经尝试了很多东西,比如索引,但是索引甚至需要更长的时间。请帮助我们,并记住我是一个新手与sql等。
非常感谢,Shabby
当然那会很慢。它必须将该函数应用于表中的每一行。它不能使用索引来最小化它必须处理的行数。
粗略的选择是“手动”限制它必须处理的行数。比如知道从“现在”回来的1小时工作时间必须至少1小时前,也许你甚至可以“知道”门票永远不会超过10天?
现在你可以......
WHERE
[plugin.tickets].[Ticket].Created >= DATEADD(DAY , -10, GETDATE())
AND [plugin.tickets].[Ticket].Created < DATEADD(Hour, -1 , GETDATE())
AND [plugin.tickets].[Ticket].status <= 2
AND [dbo].[worktime]([plugin.tickets].[Ticket].Created, GetDate()) >= 1
然后可以使用索引快速解决前三个条件(在(status, created)
上创建索引,作为单个复合索引),减少必须通过函数解析的记录数。
更好的是,写一个dateadd函数......
WHERE
[plugin.tickets].[Ticket].status <= 2
AND [plugin.tickets].[Ticket].created <= [dbo].[add_worktime]('HOUR', -1, GetDate())
现在,您的函数仅被称为ONCE(使用GETDATE()作为输入)而不是每行重复一次。并且它的结果可以用于与前面提到的相同的索引。
我百分百肯定你的查询很慢,因为:
WHILE(@CurrentDate<=@LastDate)
BEGIN
IF
(DATEPART(dw, @CurrentDate)!=1 AND DATEPART(dw, @CurrentDate)!=7)
AND @CurrentDate NOT IN
(SELECT Datum_feestdag FROM Feestdagen)
因此,为了改善这一点,我建议你在Datum_feestdag
上创建Feestdagen
的索引,并写一个像sargeable查询。
IF (DATEPART(dw, @CurrentDate)!=1 AND DATEPART(dw, @CurrentDate)!=7)
AND NOT EXISTS (SELECT Datum_feestdag
FROM Feestdagen
WHERE @CurrentDate = Datum_feestdag)