Car*_*rel 1 sql stored-procedures join subquery sql-server-2012
我是关于sql的新手,我正在尝试创建一个相当复杂的存储过程,该过程将由使用Visual Studio商业智能中的sql报告服务创建的报告使用.
我有一个主要的"项目"表,通过使用链接表(我的存储过程中感兴趣的是"状态","设施"和"分支")链接各种其他表.该应用程序的作用是研究人员提交项目,并通过以下批准过程:
专业健康经理>分科主任>健康管理团队
为了促进此批准过程,另一个团队成员开发了一个使用"WorkflowHistory"表的自定义工作流解决方案.放入此表(以及其他)的是ProjectId,WorkflowStep和执行工作流程步骤的日期以及执行该步骤的人员发布的评论.我在报告中想要的是以下内容:
我在报告中想要的信息如下:

'ProjectId'和'Title'来自'Project'表.表格中的"设施","分支"和"状态"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
Run Code Online (Sandbox Code Playgroud)
您的代码几乎没有问题:
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)
Run Code Online (Sandbox Code Playgroud)
我不知道为什么日期过滤器不起作用,对我来说没问题.我没有检查设施连接,但你应该能够很容易谷歌这个东西.我建议你将代码提取到一个函数中.然后,您可以单独测试它,查询看起来会更好.
| 归档时间: |
|
| 查看次数: |
18931 次 |
| 最近记录: |