Sql 复杂存储过程

Sql 复杂存储过程,sql,stored-procedures,join,sql-server-2012,subquery,Sql,Stored Procedures,Join,Sql Server 2012,Subquery,我是sql方面的新手,我正在尝试创建一个相当复杂的存储过程,用于在Visual Studio的Business Intelligence中使用sql reporting services创建的报表 我有一个主“Project”表,它通过使用链接表(我的存储过程中感兴趣的是“Status”、“Facility”和“Branch”)链接其他各种表。申请所做的是研究人员提交一个项目,并通过以下审批流程: 专业健康经理>分公司负责人>健康管理团队 为了简化此审批流程,另一名团队成员开发了一个自定义工作流

我是sql方面的新手,我正在尝试创建一个相当复杂的存储过程,用于在Visual Studio的Business Intelligence中使用sql reporting services创建的报表

我有一个主“Project”表,它通过使用链接表(我的存储过程中感兴趣的是“Status”、“Facility”和“Branch”)链接其他各种表。申请所做的是研究人员提交一个项目,并通过以下审批流程:

专业健康经理>分公司负责人>健康管理团队

为了简化此审批流程,另一名团队成员开发了一个自定义工作流解决方案,该解决方案利用了“WorkflowHistory”表。此表中的内容(除其他外)包括ProjectId、WorkflowStep和执行工作流步骤的日期,以及执行该步骤的人员发布的注释。我想在我的报告中包括以下内容:

我在报告中需要的信息如下:

“ProjectId”和“Title”来自“Project”表。“设施”、“分支机构”和“状态”从链接到“项目”的表中删除Received'需要为项目执行初始工作流步骤的日期。“结束”需要是为项目执行最终工作流步骤的日期。“注释”必须是留给最后一个工作流步骤的注释

因此,报告中每一行的数据来自以下位置:

  • “项目”中的一行
  • “分行”的一行
  • “状态”中的一行
  • 来自“Facility”的多行(在下面的运行尝试中,我仅返回子查询中的第一个Facility,但我希望所有分配给项目的Facility都以逗号分隔)
  • “WorkflowHistory”中的两行不同
用户传递以下参数以筛选报告:

  • 起始日期-获取特定日期后收到的所有报告(这将是“WorkflowHistory”中第一个工作流步骤的“ActionOn”)
  • 截止日期-获取特定日期之前收到的所有报告(这将是“WorkflowHistory”中最后一个工作流步骤的“ActionOn”)
  • 状态-筛选具有特定状态的项目
  • 分支-筛选指定给特定分支的项目

我已经尝试使用下面的存储过程来完成所有这一切。这是我的跑步尝试,我一直在努力。我仍然面临的问题包括:

  • 日期范围筛选不起作用
  • I只能返回子查询中的第一个工具 (以下是评论整个WHERE部分时仍然存在的问题)
  • 项目的最后一个工作流步骤可能是2到5之间的任何一个步骤,这取决于它是否被批准以及何时被拒绝。我需要弄清楚如何获得“结束”日期以及在这一步上留下的评论
  • 我在参数中传递“状态”。我需要弄清楚如何按一种状态或所有状态(实际上不是所有状态,但最后3种状态是“批准”、“拒绝”和“结束”)提交文件。分支机构也一样
编辑:现在是什么,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
创建过程[dbo]。[stp_城市健康研究请求报告]
@FromDate日期时间,
@今天的日期时间,
@StatusId int,
@布朗希德国际酒店,
@计数整数输出
像
开始
声明@attreable表
(
投射INT,
收到日期时间,
结束日期时间,
VARCHAR评论(8000)
)
如果@StatusId 0和@BranchId 0
开始
插入@tentable(项目、接收、结束、评论)
选择不同的
p、 投射的,
(选择顶部1 wf.ActionOn
来自WorkflowHistory wf
其中wf.ProjectId=p.ProjectId
和wf.WorkflowStep=1
已收到wf.WorkflowHistoryId DESC)的订单,
(选择顶部1 wf.ActionOn
来自WorkflowHistory wf
其中wf.ProjectId=p.ProjectId
和wf.WorkflowStep=4
或wf.ProjectId=p.ProjectId
和wf.WorkflowStep=5
由wf.WorkflowHistoryId DESC)完成的订单,
(选择顶部1 wf.注释
来自WorkflowHistory wf
其中wf.ProjectId=p.ProjectId
和wf.WorkflowStep=4
或wf.ProjectId=p.ProjectId
和wf.WorkflowStep=5
按wf.WorkflowHistoryId DESC)排序作为注释
从…起
项目p
在p.projectd=w.projectd上连接工作流历史记录w
在pb.projectd=p.projectd上连接ProjectBranch pb
哪里
p、 projectd=w.projectd
p.StatusId=@StatusId
和pb.BranchId=@BranchId
w.WorkflowStep=1
和(w.在@FromDate和@ToDate之间采取行动)
选择不同的
p、 投射的,
p、 头衔,
东西(
(选择“,”+f.名称
来自dbo.设施f
左连接f.FacilityId=pf.FacilityId上的dbo.ProjectFacility pf
其中pf.projectd=p.projectd
对于XML路径(“”))
,1,1,,)作为设施,
收到,
tt.总结道,
b、 布兰奇纳姆,
st.描述为状态文本,
tt.评论,
tt.结束-tt.作为周转收到
从…起
dbo.p项目
p.projectd=tt.projectd上的内部连接@attable tt
p.projectd=pb.projectd上的左连接dbo.ProjectBranch pb
在pb.BranchId=b.BranchId上左连接dbo.Branch b
左连接dbo.Status st ON p.StatusId=st.StatusId
哪里
p、 StatusId=@StatusId
b.BranchId=@BranchId
设置@Count=@@ROWCOUNT
终止
如果@StatusId 0和@BranchId=0
开始
插入@tentable(ProjectId、received、consulated、Com
-- 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)