我是sql的新手,我尝试创建一个相当复杂的存储过程,该过程将由使用Visual Studio商业智能中的sql报告服务创建的报告使用。
我有一个主要项目'通过使用链接表链接各种其他表格的表格(我的存储过程中感兴趣的是'状态','设施'分支') 。该应用程序的作用是研究人员提交项目并通过以下批准过程:
专业健康经理>分支头>健康管理团队
为了促进此审批流程,另一位团队成员开发了一个自定义工作流程解决方案,该解决方案利用了' WorkflowHistory'表。放入此表(以及其他)的是ProjectId,WorkflowStep和执行工作流程步骤的日期以及执行该步骤的人员发布的评论。我在报告中想要的是:
我在报告中想要的信息如下:
' ProjectId'和'标题'来自'项目'表。 '设施''分支'和'状态'链接到'项目'的表格中的com。 '收到'需要是为项目执行初始工作流程步骤的日期。结论'需要是为项目执行最终工作流程步骤的日期。评论'需要是留给最后工作流程步骤的评论。
因此,报告中每一行的数据来自以下地方:
用户传递以下参数以过滤报告:
我尝试使用以下存储过程完成所有这些操作。这是我的继续尝试,我一直在努力。我仍然遇到的问题包括:
编辑:现在是5小时之后,我已经更新了下面的存储过程。我通过使用临时表变量
对大部分问题进行了排序CREATE PROCEDURE [dbo].[stp_CityHealthResearchRequestsReport]
@FromDate DATETIME,
@ToDate DATETIME,
@StatusId int,
@BranchId int,
@Count INT OUTPUT
AS
BEGIN
DECLARE @TempTable TABLE
(
ProjectId INT,
Recieved DATETIME,
Concluded DATETIME,
Comment VARCHAR(8000)
)
IF @StatusId <> 0 AND @BranchId <> 0
BEGIN
INSERT INTO @TempTable (ProjectId, Recieved, Concluded, Comment)
SELECT DISTINCT
p.ProjectId,
(SELECT TOP 1 wf.ActionedOn
FROM WorkflowHistory wf
WHERE wf.ProjectId = p.ProjectId
AND wf.WorkflowStep = 1
ORDER BY wf.WorkflowHistoryId DESC) AS Recieved,
(SELECT TOP 1 wf.ActionedOn
FROM WorkflowHistory wf
WHERE wf.ProjectId = p.ProjectId
AND wf.WorkflowStep = 4
OR wf.ProjectId = p.ProjectId
AND wf.WorkflowStep = 5
ORDER BY wf.WorkflowHistoryId DESC) AS Concluded,
(SELECT TOP 1 wf.Comment
FROM WorkflowHistory wf
WHERE wf.ProjectId = p.ProjectId
AND wf.WorkflowStep = 4
OR wf.ProjectId = p.ProjectId
AND wf.WorkflowStep = 5
ORDER BY wf.WorkflowHistoryId DESC) AS Comment
FROM
Project p
JOIN WorkflowHistory w ON p.ProjectId = w.ProjectId
JOIN ProjectBranch pb ON pb.ProjectId = p.ProjectId
WHERE
p.ProjectId = w.ProjectId
AND p.StatusId = @StatusId
AND pb.BranchId = @BranchId
AND w.WorkflowStep = 1
AND (w.ActionedOn BETWEEN @FromDate AND @ToDate)
SELECT DISTINCT
p.ProjectId,
p.Title,
STUFF (
(SELECT ', ' + f.Name
FROM dbo.Facility f
LEFT JOIN dbo.ProjectFacility pf ON f.FacilityId = pf.FacilityId
WHERE pf.ProjectId = p.ProjectId
FOR XML PATH (''))
, 1, 1, '') AS Facilities,
tt.Recieved,
tt.Concluded,
b.BranchName,
st.Description AS StatusText,
tt.Comment,
tt.Concluded - tt.Recieved AS Turnaround
FROM
dbo.Project p
INNER JOIN @TempTable tt ON p.ProjectId = tt.ProjectId
LEFT JOIN dbo.ProjectBranch pb ON p.ProjectId = pb.ProjectId
LEFT JOIN dbo.Branch b ON pb.BranchId = b.BranchId
LEFT JOIN dbo.Status st ON p.StatusId = st.StatusId
WHERE
p.StatusId = @StatusId
AND b.BranchId = @BranchId
SET @Count = @@ROWCOUNT
END
IF @StatusId <> 0 AND @BranchId = 0
BEGIN
INSERT INTO @TempTable (ProjectId, Recieved, Concluded, Comment)
SELECT DISTINCT
p.ProjectId,
(SELECT TOP 1 wf.ActionedOn
FROM WorkflowHistory wf
WHERE wf.ProjectId = p.ProjectId
AND wf.WorkflowStep = 1
ORDER BY wf.WorkflowHistoryId DESC) AS Recieved,
(SELECT TOP 1 wf.ActionedOn
FROM WorkflowHistory wf
WHERE wf.ProjectId = p.ProjectId
AND wf.WorkflowStep = 4
OR wf.ProjectId = p.ProjectId
AND wf.WorkflowStep = 5
ORDER BY wf.WorkflowHistoryId DESC) AS Concluded,
(SELECT TOP 1 wf.Comment
FROM WorkflowHistory wf
WHERE wf.ProjectId = p.ProjectId
AND wf.WorkflowStep = 4
OR wf.ProjectId = p.ProjectId
AND wf.WorkflowStep = 5
ORDER BY wf.WorkflowHistoryId DESC) AS Comment
FROM
Project p
JOIN WorkflowHistory w ON p.ProjectId = w.ProjectId
JOIN ProjectBranch pb ON pb.ProjectId = p.ProjectId
WHERE
p.ProjectId = w.ProjectId
AND p.StatusId = @StatusId
AND w.WorkflowStep = 1
AND (w.ActionedOn BETWEEN @FromDate AND @ToDate)
SELECT DISTINCT
p.ProjectId,
p.Title,
STUFF (
(SELECT ', ' + f.Name
FROM dbo.Facility f
LEFT JOIN dbo.ProjectFacility pf ON f.FacilityId = pf.FacilityId
WHERE pf.ProjectId = p.ProjectId
FOR XML PATH (''))
, 1, 1, '') AS Facilities,
tt.Recieved,
tt.Concluded,
b.BranchName,
st.Description AS StatusText,
tt.Comment,
tt.Concluded - tt.Recieved AS Turnaround
FROM
dbo.Project p
INNER JOIN @TempTable tt ON p.ProjectId = tt.ProjectId
LEFT JOIN dbo.ProjectBranch pb ON p.ProjectId = pb.ProjectId
LEFT JOIN dbo.Branch b ON pb.BranchId = b.BranchId
LEFT JOIN dbo.Status st ON p.StatusId = st.StatusId
WHERE
p.StatusId = @StatusId
SET @Count = @@ROWCOUNT
END
IF @StatusId = 0 AND @BranchId <> 0
BEGIN
INSERT INTO @TempTable (ProjectId, Recieved, Concluded, Comment)
SELECT DISTINCT
p.ProjectId,
(SELECT TOP 1 wf.ActionedOn
FROM WorkflowHistory wf
WHERE wf.ProjectId = p.ProjectId
AND wf.WorkflowStep = 1
ORDER BY wf.WorkflowHistoryId DESC) AS Recieved,
(SELECT TOP 1 wf.ActionedOn
FROM WorkflowHistory wf
WHERE wf.ProjectId = p.ProjectId
AND wf.WorkflowStep = 4
OR wf.ProjectId = p.ProjectId
AND wf.WorkflowStep = 5
ORDER BY wf.WorkflowHistoryId DESC) AS Concluded,
(SELECT TOP 1 wf.Comment
FROM WorkflowHistory wf
WHERE wf.ProjectId = p.ProjectId
AND wf.WorkflowStep = 4
OR wf.ProjectId = p.ProjectId
AND wf.WorkflowStep = 5
ORDER BY wf.WorkflowHistoryId DESC) AS Comment
FROM
Project p
JOIN WorkflowHistory w ON p.ProjectId = w.ProjectId
JOIN ProjectBranch pb ON pb.ProjectId = p.ProjectId
WHERE
p.ProjectId = w.ProjectId
AND p.StatusId = 5
AND pb.BranchId = @BranchId
AND w.WorkflowStep = 1
AND (w.ActionedOn BETWEEN @FromDate AND @ToDate)
OR p.ProjectId = w.ProjectId
AND p.StatusId = 6
AND pb.BranchId = @BranchId
AND w.WorkflowStep = 1
AND (w.ActionedOn BETWEEN @FromDate AND @ToDate)
OR p.ProjectId = w.ProjectId
AND p.StatusId = 7
AND pb.BranchId = @BranchId
AND w.WorkflowStep = 1
AND (w.ActionedOn BETWEEN @FromDate AND @ToDate)
SELECT DISTINCT
p.ProjectId,
p.Title,
STUFF (
(SELECT ', ' + f.Name
FROM dbo.Facility f
LEFT JOIN dbo.ProjectFacility pf ON f.FacilityId = pf.FacilityId
WHERE pf.ProjectId = p.ProjectId
FOR XML PATH (''))
, 1, 1, '') AS Facilities,
tt.Recieved,
tt.Concluded,
b.BranchName,
st.Description AS StatusText,
tt.Comment,
tt.Concluded - tt.Recieved AS Turnaround
FROM
dbo.Project p
INNER JOIN @TempTable tt ON p.ProjectId = tt.ProjectId
LEFT JOIN dbo.ProjectBranch pb ON p.ProjectId = pb.ProjectId
LEFT JOIN dbo.Branch b ON pb.BranchId = b.BranchId
LEFT JOIN dbo.Status st ON p.StatusId = st.StatusId
WHERE
p.StatusId = 5
AND pb.BranchId = @BranchId
OR p.StatusId = 6
AND pb.BranchId = @BranchId
OR p.StatusId = 7
AND pb.BranchId = @BranchId
SET @Count = @@ROWCOUNT
END
IF @StatusId = 0 AND @BranchId = 0
BEGIN
INSERT INTO @TempTable (ProjectId, Recieved, Concluded, Comment)
SELECT DISTINCT
p.ProjectId,
(SELECT TOP 1 wf.ActionedOn
FROM WorkflowHistory wf
WHERE wf.ProjectId = p.ProjectId
AND wf.WorkflowStep = 1
ORDER BY wf.WorkflowHistoryId DESC) AS Recieved,
(SELECT TOP 1 wf.ActionedOn
FROM WorkflowHistory wf
WHERE wf.ProjectId = p.ProjectId
AND wf.WorkflowStep = 4
OR wf.ProjectId = p.ProjectId
AND wf.WorkflowStep = 5
ORDER BY wf.WorkflowHistoryId DESC) AS Concluded,
(SELECT TOP 1 wf.Comment
FROM WorkflowHistory wf
WHERE wf.ProjectId = p.ProjectId
AND wf.WorkflowStep = 4
OR wf.ProjectId = p.ProjectId
AND wf.WorkflowStep = 5
ORDER BY wf.WorkflowHistoryId DESC) AS Comment
FROM
Project p
JOIN WorkflowHistory w ON p.ProjectId = w.ProjectId
JOIN ProjectBranch pb ON pb.ProjectId = p.ProjectId
WHERE
p.ProjectId = w.ProjectId
AND p.StatusId = 5
AND w.WorkflowStep = 1
AND (w.ActionedOn BETWEEN @FromDate AND @ToDate)
OR p.ProjectId = w.ProjectId
AND p.StatusId = 6
AND w.WorkflowStep = 1
AND (w.ActionedOn BETWEEN @FromDate AND @ToDate)
OR p.ProjectId = w.ProjectId
AND p.StatusId = 7
AND w.WorkflowStep = 1
AND (w.ActionedOn BETWEEN @FromDate AND @ToDate)
SELECT DISTINCT
p.ProjectId,
p.Title,
STUFF (
(SELECT ', ' + f.Name
FROM dbo.Facility f
LEFT JOIN dbo.ProjectFacility pf ON f.FacilityId = pf.FacilityId
WHERE pf.ProjectId = p.ProjectId
FOR XML PATH (''))
, 1, 1, '') AS Facilities,
tt.Recieved,
tt.Concluded,
b.BranchName,
st.Description AS StatusText,
tt.Comment,
tt.Concluded - tt.Recieved AS Turnaround
FROM
dbo.Project p
INNER JOIN @TempTable tt ON p.ProjectId = tt.ProjectId
LEFT JOIN dbo.ProjectBranch pb ON p.ProjectId = pb.ProjectId
LEFT JOIN dbo.Branch b ON pb.BranchId = b.BranchId
LEFT JOIN dbo.Status st ON p.StatusId = st.StatusId
WHERE
p.StatusId = 5
OR p.StatusId = 6
OR p.StatusId = 7
SET @Count = @@ROWCOUNT
END
END
答案 0 :(得分:5)
您的代码几乎没有问题:
WHERE
子句中处理它。说够了,我相信这个查询可以做你想要的:
-- find out the final step for each project
WITH FinalStep AS
(
SELECT ProjectId, MAX(WorkflowStep) as MaxWorkflowStep
FROM WorkflowHistory
WHERE WorkflowStep > 1
GROUP BY ProjectId
)
SELECT
p.ProjectId,
p.Title,
-- this is ugly consider creating a scalar function to encapsulate it
STUFF (
(SELECT ', ' + f.Name
FROM dbo.Facility f
LEFT JOIN dbo.ProjectFacility pf ON f.FacilityId = pf.FacilityId
WHERE pf.ProjectId = p.ProjectId
FOR XML PATH (''))
, 1, 1, '') AS Facilities,
wf1.ActionedOn AS Recieved,
wf2.ActionedOn AS Concluded,
b.BranchName,
st.Description AS StatusText,
wf2.Comment,
wf2.ActionedOn - w1.ActionedOn AS Turnaround
FROM
Project p
INNER JOIN WorkflowHistory wf1
ON p.ProjectId = wf1.ProjectId
AND wf1.WorkflowStep = 1
LEFT JOIN FinalStep fs
ON fs.ProjectId = p.ProjectId
LEFT JOIN WorkflowHistory wf2
ON p.ProjectId = wf2.ProjectId
AND wf2.WorkflowStep = fs.MaxWorkflowStep
INNER JOIN ProjectBranch pb
ON pb.ProjectId = p.ProjectId
LEFT JOIN dbo.Branch b
ON pb.BranchId = b.BranchId
LEFT JOIN dbo.Status st
ON p.StatusId = st.StatusId
WHERE
p.ProjectId = w.ProjectId
-- IF @StatusId = 0 THEN p.StatusId = 5 or 6 or 7 ELSE p.StatusId = @StatusId
AND ((@StatusId = 0 AND p.StatusId IN (5,6,7)) OR p.StatusId = @StatusId)
-- IF @BranchId = 0 THEN no filter ELSE pb.BranchId = @BranchId
AND (@BranchId = 0 OR pb.BranchId = @BranchId)
AND (wf1.ActionedOn BETWEEN @FromDate AND @ToDate)
我不知道为什么日期过滤器不起作用,对我来说没问题。我没有检查设施连接,但你应该能够很容易谷歌这个东西。我建议你将代码提取到一个函数中。然后,您可以单独测试它,查询看起来会更好。