SQL Server - 返回在顺序记录中具有重复值的集合

时间:2013-04-26 19:28:10

标签: sql-server tsql

我的数据如下所示:
数据按processID排序,然后按步骤开始日期排序 步骤开始日期确定步骤的顺序。 每个步骤都经过审批人批准(下面的审批者ID是任意的)

╔═══════════╦══════════════════════════╦═══════════════╦════════════╗
║ ProcessID ║         StepName         ║Step Start Date║ ApproverID ║
╠═══════════╬══════════════════════════╬═══════════════╬════════════╣
║         1 ║ Supervisor Approval      ║1/1/2013 07:24 ║ A          ║
║         1 ║ Sales Manager Approval   ║1/1/2013 13:35 ║ B          ║
║         1 ║ General Manager Approval ║1/3/2013 08:00 ║ B          ║
║         1 ║ CEO Approval             ║1/5/2013 14:40 ║ C          ║
║         2 ║ Supervisor Approval      ║1/2/2013 07:00 ║ A          ║
║         2 ║ Sales Manager Approval   ║1/2/2013 08:00 ║ B          ║
║         2 ║ General Manager Approval ║1/2/2013 09:00 ║ C          ║
║         2 ║ CEO Approval             ║1/2/2013 10:00 ║ B          ║
╚═══════════╩══════════════════════════╩═══════════════╩════════════╝

我需要一个TSQL查询,它会为2个或更多连续步骤中具有相同ApproverID的任何进程返回[ProcessID]。

因此,在上面的示例中,将返回ProcessID#1,因为审批者B批准了步骤2和3(连续)。不会返回ProcessID#2,因为即使审批人B批准了第2步和第4步,它们也不是连续的。

以下是使用架构设置和一些示例数据的SQL小提琴:SQL Fiddle

非常感谢任何帮助!

2 个答案:

答案 0 :(得分:1)

这将根据您的数据集中的需要返回进程1:

with nextSteps as
(
  select s.ProcessID
    , disapprove = case when s.ApproverID <= n.ApproverID or n.ApproverID is null
      then 0 else 1 end
  from steps s
    outer apply
    (
      select top 1 ApproverID
      from steps n
      where s.ProcessID = n.ProcessID
        and s.StepStartDate < n.StepStartDate
      order by n.StepStartDate
    ) n
)
select ProcessID
from nextSteps
group by ProcessID
having sum(disapprove) = 0

SQL Fiddle with demo

基本上对于每个流程步骤,我们在同一流程中进行下一步,并检查下一步是由相同或更大的审批者。

如果一行或多行失败,请不要返回ProcessID。

评论后修改:

with nextSteps as
(
  select s.ProcessID
    , disapprove = case when s.ApproverID = n.ApproverID then 1 else 0 end
  from steps s
    outer apply
    (
      select top 1 ApproverID
      from steps n
      where s.ProcessID = n.ProcessID
        and s.StepStartDate < n.StepStartDate
      order by n.StepStartDate
    ) n
)
select ProcessID
from nextSteps
group by ProcessID
having sum(disapprove) > 0

SQL Fiddle with demo

这个稍微改变的新查询适用于以下审批者模式,如SQL Fiddle:

所示

进程ID 1:A,B,B,C - 应该返回连续批准者。

ProcessID 2:A,B,C,B - 没有连续批准者,不应该退回。

进程ID 3:A,B,C,D - 没有连续的批准者,不应该返回。

非常相似,检查ProcessID中每个步骤的下一行,如果至少有一个连续的批准者,则返回ProcessID。

我还检查了你添加的SQL Fiddle中的数据 - 似乎正在运行:

SQL Fiddle with more data

答案 1 :(得分:0)

这是我最终得到的结果,感谢Ian的帮助:

WITH Steps AS
(
  SELECT
    [CurStep].[ProcessID],
    ConsecutiveApproval =
      CASE
        WHEN [CurStep].[ApproverID] = [NextStep].[ApproverID] THEN 1
        ELSE 0
      END
  FROM [Processes] AS CurStep
    OUTER APPLY
    (
      SELECT TOP 1
        [NextStep].[ApproverID]
      FROM
        [Processes] AS NextStep
      WHERE
        [CurStep].[ProcessID] = [NextStep].[ProcessID]
        AND [CurStep].[StepStartDate] < [NextStep].[StepStartDate]
      ORDER BY [NextStep].[StepStartDate]
    ) AS NextStep
)
SELECT   [ProcessID]
FROM     [Steps]
GROUP BY [Steps].[ProcessID]
HAVING   SUM([ConsecutiveApproval]) > 0

Working SQL Fiddle