2

对于每个 WorkflowId 分组,我想计算一个 20 的流程代码在 10 的流程代码之前有多少次 LastModifiedTime。

此查询显示表布局和一些数据:

SELECT TOP 10 * 
FROM master.ProcessLogging with (nolock) 
WHERE ProcessCode = 10 OR ProcessCode = 20 
ORDER BY WorkflowId, ProcessCode

在此处输入图像描述

我已经尝试了一些东西,但我很难让它发挥作用。每次尝试都导致了不值得在这里发布的死胡同。有没有办法查看 20 出现在 10 之前的所有时间?甚至可能看到它们之间的时差?

4

4 回答 4

2

经审查,如果一组中超过 10 个,这将中断

一个组中是否会超过 10 个,如果是,您希望如何处理?

SELECT p10.WorkflowId, count(p20.WorkflowId)
FROM master.ProcessLogging p10 
left outer join master.ProcessLogging p20
  on  p20.WorkflowId = p10.WorkflowId
  and p20.EventTime < p10.EventTime
  and p20.ProcessCode = 20
where p10.ProcessCode = 10 
group by p10.WorkflowId 
order by p10.WorkflowId

--来自 Bob Horn 的编辑--

对上面的查询稍作修改,以显示 10s 和 20s 之间的最大时间差。

SELECT p10.WorkflowId, min(p20.WorkflowId), 
       DATEDIFF(ms, min(p10.lastmodifiedtime), min(p20.lastmodifiedtime)) as 'Diff (ms)'
FROM master.ProcessLogging p10 
join master.ProcessLogging p20
  on  p20.WorkflowId = p10.WorkflowId
  and p20.EventTime < p10.EventTime
  and p20.ProcessCode = 20
where p10.ProcessCode = 10 
group by p10.WorkflowId 
order by ABS(DATEDIFF(ms, min(p10.lastmodifiedtime), min(p20.lastmodifiedtime))) DESC
于 2012-09-27T17:03:15.990 回答
1

我想您可以在查询中添加一个行号,然后将其包装在 SELECT WHERE PROCESSCODE=20 AND (SELECT PROCESSCODE FROM [same query] WHERE rownumber=rownumber+1)=10 中。或类似的东西。还没有弄清楚细节。

于 2012-09-27T17:04:38.083 回答
1

这应该这样做

with cte as (
    SELECT *,
        row_number() over (partition by WorkflowId order by ProcessCode) as [a] ,
        row_number() over (partition by WorkflowId order by LastModifiedTime) as [b]
    FROM master.ProcessLogging with (nolock) 
    WHERE ProcessCode = 10 OR ProcessCode = 20 
)
select * from cte
where [a] - [b] <> 0

作为解释,我为每个 WorkflowId 获得了两个不同的排名。如果进程代码的顺序正确(即升序),则两个排名相同,差值为0。否则,排名不同,差值非零。

于 2012-09-27T17:35:01.177 回答
1

如果基于 LastModifiedTime 的每个 WorkflowId 总是应该最后一个 20,那么这很简单。您甚至不必查看 EventTime。不需要 Row_Number:

SELECT *
FROM
   master.ProcessLogging L
WHERE
   L.ProcessCode = 20
   AND EXISTS (
      SELECT *
      FROM master.ProcessLogging L2
      WHERE
         L.WorkflowId = L2.WorkflowId
         AND L.LastModifiedTime < L2.LastModifiedTime
         AND L2.ProcessCode = 10
   )

这将为每个乱序工作流返回一行,因此您可以轻松地将其更改为SELECT Count(*)而不是SELECT *.

如果 EventTime 也变得很重要,您可以将其添加到 exists 子句中,作为与 LastModifiedTime 的 OR。

我刚刚注意到您想要它们之间的时间差(通过显示每行的详细信息意味着您不能返回单个计数)。这是一个可以在 SQL 2005 及更高版本中执行此操作的查询。如果您使用的不是 SQL Server 2005,请告诉我们,我会为您写一个不同的查询。

SELECT
   *,
   MinutesApart = DateDiff(minute, L.LastModifiedTime, L2.LastModifiedTime)
FROM
   master.ProcessLogging L
   CROSS APPLY (
      SELECT TOP 1 *
      FROM master.ProcessLogging L2
      WHERE
         L.WorkflowId = L2.WorkflowId
         AND L.LastModifiedTime < L2.LastModifiedTime
         AND L2.ProcessCode = 10
      ORDER BY L2.LastModifiedTime DESC
   ) L2
WHERE
   L.ProcessCode = 20

请注意,如果您在 20 之后有多个 10 个代码,则只会显示最差的一个。要查看所有这些(并每 20 个代码获取多行),您可以将其更改为简单的自联接:

SELECT
   *,
   MinutesApart = DateDiff(minute, L.LastModifiedTime, L2.LastModifiedTime)
FROM
   master.ProcessLogging L
   INNER JOIN master.ProcessLogging L2
      ON L.WorkflowId = L2.WorkflowId
WHERE
   L.ProcessCode = 20
   AND L2.ProcessCode = 10
   AND L.LastModifiedTime < L2.LastModifiedTime
于 2012-09-27T17:41:37.503 回答