我在SQL Server 2005中有这个查询:
SELECT J.JobID,
dbo.tblCustomers.Name AS CustomerName,
J.CustomerJobNumber,
J.JobName,
(CASE WHEN [tblCustomers].[CoreCust] = 0 THEN 'AUXILIARY' ELSE 'CORE' END) AS Department,
J.JobStatusID,
dbo.tblJobTypes.JobType
FROM dbo.tblJobs (NOLOCK) AS J
INNER JOIN dbo.tblCustomers (NOLOCK) ON J.CustomerID = dbo.tblCustomers.CustomerID
INNER JOIN dbo.tblJobTypes (NOLOCK) ON J.JobTypeID = dbo.tblJobTypes.JobTypeID
INNER JOIN dbo.tblDepartments (NOLOCK) ON J.DepartmentId = dbo.tblDepartments.DepartmentID
WHERE (J.Closed = 0)
AND (J.Invoiced = 0)
AND (J.Active = 1)
AND (dbo.fncIsAllPointsDelivered(J.JobID) = 1)
AND (J.DepartmentId <> 2)
此查询运行时间太长,我知道问题是UDF - (dbo.fncIsAllPointsDelivered(J.JobID)= 1) - 。
UDF的SQL在这里:
DECLARE @DetailCount int
DECLARE @TrackingCount int
SELECT @DetailCount = COUNT(*)
FROM [dbo].[tblLoadDetails] (NOLOCK)
WHERE JobId = @JobId
SELECT @TrackingCount = COUNT(*)
FROM [dbo].[tblLoadDetails] (NOLOCK)
WHERE JobId = @JobId AND Delivered = 1
IF(@DetailCount = @TrackingCount AND @DetailCount > 0)
RETURN 1
RETURN 0
除非作业中包含大量的装载细节,否则所有这些都会非常快速地运行。我试图想办法让UDF更快或摆脱UDF的需要,但我不知所措。我希望你们中的一些SQL大师能够帮助我。
答案 0 :(得分:5)
SELECT *
FROM tblJobs j
INNER JOIN
tblCustomers c
ON c.CustomerID = J.CustomerID
INNER JOIN
tblJobTypes jt
ON jt.JobTypeID = J.JobTypeID
INNER JOIN
tblDepartments d
ON d.DepartmentID = J.DepartmentId
WHERE J.Closed = 0
AND J.Invoiced = 0
AND J.Active = 1
AND J.DepartmentId <> 2
AND J.JobID IN
(
SELECT JobID
FROM tblLoadDetails
)
AND J.JobID NOT IN
(
SELECT JobID
FROM tblLoadDetails
WHERE Delivered <> 1
)
在这些字段上创建综合索引:
tblJobs (Closed, Invoiced, Active) INCLUDE (DepartmentID)
如果您的tblLoadDetails.Delivered
是位字段,则创建以下索引:
tblLoadDetail (JobID, Delivered)
并重写最后一个条件:
SELECT *
FROM tblJobs j
INNER JOIN
tblCustomers c
ON c.CustomerID = J.CustomerID
INNER JOIN
tblJobTypes jt
ON jt.JobTypeID = J.JobTypeID
INNER JOIN
tblDepartments d
ON d.DepartmentID = J.DepartmentId
WHERE J.Closed = 0
AND J.Invoiced = 0
AND J.Active = 1
AND J.DepartmentId <> 2
AND
(
SELECT TOP 1 Delivered
FROM tblLoadDetails ld
WHERE ld.JobID = j.JobID
ORDER BY
Delivered
) = 1
答案 1 :(得分:1)
我是从头顶开始工作的,所以我没有试过这个。但我认为你可以这样做来删除这个功能。用这两个子句替换对函数的调用。这假设'Delivered'是一个BIT字段:
AND EXISTS (SELECT 1 FROM tblLoadDetails WHERE JobID = J.JobID)
AND NOT EXISTS (SELECT 1 FROM tblLoadDetails WHERE JobID = J.JobID AND Delivered = 0)
AND EXISTS
涵盖UDF的@DetailCount > 0
检查;然后,AND NOT EXISTS
涵盖了@ DetailCount = @TrackingCount
,我所做的假设是,您正在查看作业是否存在以及是否已完成该作业。所以,如果有一件事情尚未交付,则需要将其排除在外。
如上所述:从头顶开始,因此没有经过测试或未进行过剖析。我想我的逻辑是正确的。如果没有, 应该是的简单变体。