我编写了这个函数,该函数提供给XSLT工具进行报告。它非常慢,平均需要1.5-2秒才能返回100行。这会变得更糟,因为此查询最多可以返回2000行。任何类型的超额负载都会导致查询超时,所以现在我需要优化它。
USE [ININ_SID]
GO
/****** Object: UserDefinedFunction [dbo].[GetProjectData] Script Date: 12/30/2011 10:27:22 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
ALTER FUNCTION [dbo].[GetProjectData] (
-- Add the parameters for the function here
@ProjectNo VARCHAR(100))
RETURNS @Final TABLE (
Customer VARCHAR(250),
ProjectNo VARCHAR(50),
ProjectName VARCHAR(512),
ProjectType VARCHAR(100),
PhaseID INT,
Phase VARCHAR(50),
NameField1 VARCHAR(100),
IDField1 INT,
IDField2 INT,
ItemDescription VARCHAR(100),
Health VARCHAR(6),
CompletionPercentage INT,
Status VARCHAR(16),
Owner VARCHAR(64),
ItemNotes VARCHAR(140),
ProjectNotes VARCHAR(140))
AS
BEGIN
DECLARE @Health TABLE (
ProjectID INT,
ProjectNotes VARCHAR(140))
DECLARE @Projects TABLE (
ProjectID INT PRIMARY KEY,
ProjectSiteId INT,
ProjectNo VARCHAR(50),
ProjectType VARCHAR(100),
ProjectName VARCHAR(512),
Customer VARCHAR(250),
UNIQUE (ProjectID))
INSERT INTO @Projects
SELECT PSO_Projects.ProjectID,
ProjectSiteID,
ProjectNo,
ProjectType,
ProjectName,
Customers.Name AS Customer
FROM PSO_Projects
INNER JOIN Customers
ON Customers.CustomerID = PSO_Projects.CustomerID
WHERE PSO_Projects.ProjectNo = @ProjectNo
AND CompletionDate IS NULL
-- Get the latest health/notes for the projects
-- This will be used in an inner join later
INSERT INTO @Health
SELECT ProjectID,
ProjectNotes
FROM (SELECT ProjectID,
Notes AS ProjectNotes,
Rank() OVER (Partition BY ProjectID ORDER BY LastUpdatedDate DESC) AS Rank
FROM PSO_ProjectHealthEntries) tmp
WHERE Rank = 1
AND ProjectID IN (SELECT ProjectID
FROM @Projects)
-- PROJECT DELIVERABLES
INSERT INTO @Final
(Customer,
ProjectNo,
ProjectName,
ProjectType,
PhaseID,
Phase,
NameField1,
IDField1,
IDField2,
ItemDescription,
Health,
CompletionPercentage,
Status,
Owner,
ItemNotes,
ProjectNotes)
SELECT Customer,
ProjectNo,
ProjectName,
ProjectType,
PSO_phases.PhaseID,
PSO_Phases.Name,
PSO_Phases.PhaseType,
PSO_Deliverables.DeliverableID,
PSO_Deliverables.MasterID,
PSO_Deliverables.Name,
PSO_Deliverables.Health,
PSO_Deliverables.CompletionPercentage,
pso_deliverables.Status,
DeliverableContacts.Name,
PSO_Deliverables.Notes,
Health.ProjectNotes
FROM @Projects Projects
INNER JOIN @Health Health
ON Health.ProjectID = Projects.ProjectID
INNER JOIN PSO_Phases
ON PSO_Phases.ProjectSiteID = Projects.ProjectSiteID
LEFT JOIN PSO_Deliverables
ON PSO_Deliverables.PhaseID = PSO_Phases.PhaseID
LEFT JOIN PSO_DeliverableAssociations
ON PSO_DeliverableAssociations.DeliverableID = PSO_Deliverables.DeliverableID
AND PSO_DeliverableAssociations.Active = 1
LEFT JOIN PSO_ProjectContacts DeliverableContacts
ON DeliverableContacts.ContactID = PSO_DeliverableAssociations.ContactID
WHERE PSO_Phases.Name 'System Development & Deployment'
AND PSO_Deliverables.Type NOT IN (SELECT DISTINCT ManagementGroup
FROM PSO_DeliverableOwnership)
AND Projects.ProjectID IN (SELECT ProjectID
FROM @Projects)
-- ADDON DELIVERABLES
INSERT INTO @Final
(Customer,
ProjectNo,
ProjectName,
ProjectType,
PhaseID,
Phase,
NameField1,
IDField1,
IDField2,
ItemDescription,
Health,
CompletionPercentage,
Status,
Owner,
ItemNotes,
ProjectNotes)
SELECT Customer,
ProjectNo,
ProjectName,
ProjectType,
PSO_Phases.PhaseID,
'Add-On Deliverables',
PSO_Deliverables.SubType,
PSO_Deliverables.DeliverableID,
PSO_Deliverables.MasterID,
PSO_Deliverables.Name + ' (' + PSO_Deliverables.SubType + ')',
PSO_Deliverables.Health,
PSO_Deliverables.CompletionPercentage,
PSO_Deliverables.Status,
PSO_ProjectContacts.Name,
PSO_Deliverables.Notes,
Health.ProjectNotes
FROM @Projects Projects
INNER JOIN @Health Health
ON Health.ProjectID = Projects.ProjectID
INNER JOIN PSO_Phases
ON PSO_Phases.ProjectSiteID = Projects.ProjectSiteID
INNER JOIN PSO_Deliverables
ON PSO_Deliverables.PhaseID = PSO_Phases.PhaseID
LEFT JOIN PSO_DeliverableAssociations
ON PSO_DeliverableAssociations.DeliverableID = PSO_Deliverables.DeliverableID
AND PSO_DeliverableAssociations.Active = 1
LEFT JOIN PSO_ProjectContacts
ON PSO_ProjectContacts.ContactID = PSO_DeliverableAssociations.ContactID
WHERE Projects.ProjectID IN (SELECT ProjectID
FROM @Projects)
AND ( PSO_Deliverables.Type IN (SELECT DISTINCT ManagementGroup
FROM PSO_DeliverableOwnership) )
-- PROJECT SITE NAMES ONLY
INSERT INTO @Final
(Customer,
ProjectNo,
ProjectName,
ProjectType,
PhaseID,
Phase,
NameField1,
IDField1,
IDField2,
ItemDescription,
Health,
CompletionPercentage,
Status,
Owner,
ItemNotes,
ProjectNotes)
SELECT Customer,
ProjectNo,
ProjectName,
ProjectType,
0,
'Systems Development and Deployment',
PSO_Sites.Name,
PSO_Sites.SiteID,
PSO_Sites.SiteID,
PSO_Sites.Name,
'' AS Health,
'' AS CompletionPercentage,
'' AS Status,
'' AS Owner,
'' AS Notes,
Health.ProjectNotes
FROM @Projects Projects
INNER JOIN @Health Health
ON Health.ProjectID = Projects.ProjectID
INNER JOIN PSO_Sites
ON PSO_Sites.ProjectID = Projects.ProjectID
WHERE Projects.ProjectID IN (SELECT ProjectID
FROM @Projects)
RETURN
END
除此之外,订单非常重要。这就是它的名称:
SELECT Data.*
FROM PSO_Projects
INNER JOIN PSO_ProjectAssociations
ON PSO_ProjectAssociations.ProjectID = PSO_Projects.ProjectID
AND PSO_ProjectAssociations.Active = 1
INNER JOIN PSO_ProjectContacts
ON PSO_ProjectContacts.ContactID = PSO_ProjectAssociations.ContactID
CROSS apply Getprojectdata(ProjectNo) Data
WHERE PSO_ProjectContacts.Name = 'John.Smith'
AND PSO_Projects.CompletionDate IS NULL
ORDER BY Customer,
ProjectNo,
CASE
WHEN Phase = 'Initiation' THEN PhaseID
WHEN Phase = 'Planning' THEN PhaseID + 2000
WHEN Phase = 'Requirements & Design' THEN PhaseID + 4000
WHEN Phase = 'Systems Development and Deployment' THEN PhaseID + 6000
WHEN Phase = 'Add-On Deliverables' THEN PhaseID + 8000
WHEN Phase = 'Closing' THEN PhaseID + 10000
ELSE PhaseID
END,
IDField2,
IDField1
我可以在查询中做些什么来优化它?我唯一的另一个选择是找到一种方法来重构报表,以便能够处理更少的列(例如将项目名称/客户返回到一行而不是将其包含在每一行中)但我不确定这是多么可行。
答案 0 :(得分:3)
快速点击,只需取出not in
并使用not exists
,检查ProjectID的所有in
语句都无用。将插入插入@Final
一个unioned
语句,如下所示:
SELECT
Customer,
ProjectNo,
ProjectName,
ProjectType,
PSO_phases.PhaseID,
PSO_Phases.Name,
PSO_Phases.PhaseType,
PSO_Deliverables.DeliverableID,
PSO_Deliverables.MasterID,
PSO_Deliverables.Name,
PSO_Deliverables.Health,
PSO_Deliverables.CompletionPercentage,
pso_deliverables.Status,
DeliverableContacts.Name,
PSO_Deliverables.Notes,
Health.ProjectNotes
FROM
@Projects Projects
INNER JOIN @Health Health
ON Health.ProjectID = Projects.ProjectID
INNER JOIN PSO_Phases
ON PSO_Phases.ProjectSiteID = Projects.ProjectSiteID
LEFT JOIN PSO_Deliverables
ON PSO_Deliverables.PhaseID = PSO_Phases.PhaseID
LEFT JOIN PSO_DeliverableAssociations
ON PSO_DeliverableAssociations.DeliverableID = PSO_Deliverables.DeliverableID
AND PSO_DeliverableAssociations.Active = 1
LEFT JOIN PSO_ProjectContacts DeliverableContacts
ON DeliverableContacts.ContactID = PSO_DeliverableAssociations.ContactID
WHERE
PSO_Phases.Name = 'System Development & Deployment'
AND NOT EXISTS (
SELECT
1
FROM
PSO_DeliverableOwnership
where
PSO_Deliverables.Type = ManagementGroup
)
union all
SELECT Customer,
ProjectNo,
ProjectName,
ProjectType,
PSO_Phases.PhaseID,
'Add-On Deliverables',
PSO_Deliverables.SubType,
PSO_Deliverables.DeliverableID,
PSO_Deliverables.MasterID,
PSO_Deliverables.Name + ' (' + PSO_Deliverables.SubType + ')',
PSO_Deliverables.Health,
PSO_Deliverables.CompletionPercentage,
PSO_Deliverables.Status,
PSO_ProjectContacts.Name,
PSO_Deliverables.Notes,
Health.ProjectNotes
FROM @Projects Projects
INNER JOIN @Health Health
ON Health.ProjectID = Projects.ProjectID
INNER JOIN PSO_Phases
ON PSO_Phases.ProjectSiteID = Projects.ProjectSiteID
INNER JOIN PSO_Deliverables
ON PSO_Deliverables.PhaseID = PSO_Phases.PhaseID
LEFT JOIN PSO_DeliverableAssociations
ON PSO_DeliverableAssociations.DeliverableID = PSO_Deliverables.DeliverableID
AND PSO_DeliverableAssociations.Active = 1
LEFT JOIN PSO_ProjectContacts
ON PSO_ProjectContacts.ContactID = PSO_DeliverableAssociations.ContactID
WHERE
NOT EXISTS (
SELECT
1
FROM
PSO_DeliverableOwnership
where
PSO_Deliverables.Type = ManagementGroup
)
union all
SELECT Customer,
ProjectNo,
ProjectName,
ProjectType,
0,
'Systems Development and Deployment',
PSO_Sites.Name,
PSO_Sites.SiteID,
PSO_Sites.SiteID,
PSO_Sites.Name,
'' AS Health,
'' AS CompletionPercentage,
'' AS Status,
'' AS Owner,
'' AS Notes,
Health.ProjectNotes
FROM @Projects Projects
INNER JOIN @Health Health
ON Health.ProjectID = Projects.ProjectID
INNER JOIN PSO_Sites
ON PSO_Sites.ProjectID = Projects.ProjectID
答案 1 :(得分:0)
这是将@tables拉入一个查询的开始。继续构建,直到您有一个查询。这可以是一个查询(带有联合)对于不存在或不存在通常是左外连接,然后在右边的表上搜索null将提供最佳性能。
SELECT Customer,
ProjectNo,
ProjectName,
ProjectType,
PSO_phases.PhaseID,
PSO_Phases.Name,
PSO_Phases.PhaseType,
PSO_Deliverables.DeliverableID,
PSO_Deliverables.MasterID,
PSO_Deliverables.Name,
PSO_Deliverables.Health,
PSO_Deliverables.CompletionPercentage,
pso_deliverables.Status,
DeliverableContacts.Name,
PSO_Deliverables.Notes,
Health.ProjectNotes
FROM PSO_Projects
INNER JOIN Customers
ON Customers.CustomerID = PSO_Projects.CustomerID
AND CompletionDate IS NULL
INNER JOIN PSO_Phases
ON PSO_Phases.ProjectSiteID = Projects.ProjectSiteID
LEFT JOIN PSO_Deliverables
ON PSO_Deliverables.PhaseID = PSO_Phases.PhaseID
LEFT JOIN PSO_DeliverableAssociations
ON PSO_DeliverableAssociations.DeliverableID = PSO_Deliverables.DeliverableID
AND PSO_DeliverableAssociations.Active = 1
LEFT JOIN PSO_ProjectContacts DeliverableContacts
ON DeliverableContacts.ContactID = PSO_DeliverableAssociations.ContactID
INNER JOIN @Health Health
ON Health.ProjectID = Projects.ProjectID
left outer join PSO_DeliverableOwnership
ON SO_DeliverableOwnership.ManagementGroup = PSO_Deliverables.Type
WHERE PSO_Phases.Name = 'System Development & Deployment'
AND PSO_Projects.ProjectNo = @ProjectNo
AND PSO_Projects.CompletionDate IS NULL
AND SO_DeliverableOwnership.ManagementGroup is null
同意工会
@Health我认为会在函数
中做到这一点 SELECT top 1 Notes from PSO_ProjectHealthEntries where ProjectID = @inputID
毫无疑问我有些错误,但你加入@table的地方用实际的连接代替。对于查询优化器使用,@ table没有PK,FK。