0

我有一个每秒接收行的表,每秒传递一个活动状态以及时间戳。我需要根据状态的特定变化进行分组,例如当状态从 6 变为 0 时,然后所有后面的 0 直到状态再次发生变化。解释这个问题的最好方法是一个例子:

|时间戳 | 州|

|13:05:00 | 1 |
|13:05:05 | 0 |
|13:05:10 | 0 |
|13:05:15 | 6 |
|13:05:20 | 6 |
|13:05:25 | 0 |
|13:05:30 | 0 |
|13:05:35 | 6 |
|13:05:40 | 6 |
|13:05:45 | 0 |
|13:05:50 | 0 |

我希望能够从这个表中得到的结果是 2 组,(从 6 到 0 有 2 次状态变化)将所有 0 状态分组,这些状态跟随状态 6,直到状态再次发生变化。<13:05:25,13:05:30>;<13:05:45,13:05:50>

4

2 回答 2

1
    CREATE TABLE MyTable
    (
      [TimeStamp] NVARCHAR(10),
      [State] INT
    )

    INSERT INTO MyTable ([TimeStamp], [State])
    SELECT '13:05:00', 1
    UNION ALL
    SELECT '13:05:05', 0
    UNION ALL
    SELECT '13:05:10', 0
    UNION ALL
    SELECT '13:05:15', 6
    UNION ALL
    SELECT '13:05:20', 6
    UNION ALL
    SELECT '13:05:25', 0
    UNION ALL
    SELECT '13:05:30', 0
    UNION ALL
    SELECT '13:05:35', 6
    UNION ALL
    SELECT '13:05:40', 6
    UNION ALL
    SELECT '13:05:45', 0
    UNION ALL
    SELECT '13:05:50', 0
    GO

;WITH cte( [RowNum], [TimeStamp], [State]) AS
(
  SELECT ROW_NUMBER() OVER(ORDER BY TIMESTAMP), TIMESTAMP, STATE FROM MyTable
)
SELECT 
t2.TimeStamp AS [Start],
ISNULL
(
  (SELECT TimeStamp FROM cte WHERE RowNum = (SELECT TOP 1 RowNum FROM cte WHERE State <> 0 AND RowNum > t2.RowNum ORDER BY TimeStamp)-1)
  ,(SELECT MAX(TimeStamp) FROM cte)
) [End]
FROM cte t1
JOIN cte t2 ON t1.RowNum = t2.RowNum - 1
WHERE t1.State = 6 AND t2.State = 0
GO

尝试在 Fiddle

于 2013-07-08T12:04:19.100 回答
0

不确定问题是否足够清楚:| 所以我以另一种方式接近它,因为发现从 6 到 0 的第一个变化很容易做到:

with x as (
  select *, rn = ROW_NUMBER() OVER (ORDER BY Activity_Time)
  FROM WellData_Activity
  )
  Select x.Activity_Code, x.Activity_Time
  from x left outer join x as y
  on x.rn = y.rn + 1
  and x.Activity_Code <> y.Activity_Code
  where y.activity_code is not null

但是一系列activity_codes的分组更难同时完成,所以我用它首先对它们进行分组(按时间顺序的activity_code),然后我可以运行第一个查询以返回一行(现在返回开始/结束):

WITH periods AS (
SELECT
    *,
    grp = ROW_NUMBER() OVER (PARTITION BY Well_GUID        ORDER BY Activity_Time)
    - ROW_NUMBER() OVER (PARTITION BY Well_GUID, Activity_Code ORDER BY Activity_Time)
  FROM WellData_Activity
)
SELECT
  Well_GUID,
  date_from = MIN(Activity_Time),
  date_to   = MAX(Activity_Time),
  Activity_Code
FROM periods
GROUP BY
Well_GUID,
Activity_Code,
grp
ORDER BY
Well_GUID,
MIN(Activity_Time)
于 2013-07-08T12:02:54.277 回答