[列]在N时间内未更改

时间:2013-11-18 14:03:13

标签: sql sql-server-2012

所以,我有一个观点,即不能很好地编入索引,而且我无能为力。

该视图的数据看起来有点像this question中的那个,但我的问题基本上与他们的问题相反,我不确定他们的解决方案是否适用于此,尽管类似的TVF或CTE很可能在预测中。

我的数据目前看起来像这样:

CustomPollerAssignmentId     DateTime                Status
[Some Id B]                    2013-11-18 08:54:00   IDLE
[Some Id A]                    2013-11-18 08:54:00   DORMANT
[Some Id B]                    2013-11-18 08:53:00   IDLE
[Some Id A]                    2013-11-18 08:53:00   NOMINAL

与其他问题不同,我需要看到状态没有改变。该视图包含三个单独的表。一个包含十分钟统计数据,一个包含十五分钟统计数据(三到六个月前),另一个包含每小时统计数据(一年前)(

)。

此处的目标是检查哪些调制解调器已空闲至少在过去10分钟。我们有大约1200个活动调制解调器,所以这可能多达12000行,这就是为什么我不想用C#做这个,但我仍然是SQL和基于集合思维的新手。我目前正在使用SQL Server 2012的一个实例,但它在这里很新,而且我对使用较新的窗口函数并不熟悉,因为我们在2008R2直到大约一个月之前。

说实话,我甚至不确定从哪里开始,因为我的OOP背景要求我只抓住每个的TOP 10状态并循环。如果全部10 ==空闲||休眠,添加到结果集,但我知道在SQL中必须有更好的方法。有人能指出我正确的方向吗?

修改

试着澄清一下:

  1. 我正在使用T-SQL。

  2. 这不像WHERE NOT EXISTS子句那么简单。

  3. 无论状态是否已更改,除非已取消激活,否则应存在远程状态的条目。这意味着它可以具有最后10分钟的(空闲,空闲,空闲,空闲,空闲,标称,空闲,空闲,空闲,空闲)状态,并且该示例是我不想要包括的情况。结果集应仅包括那些在过去10分钟内只有闲置或休眠状态的遥控器。如果最后一个状态超过三个月,则只有一个状态,间隔为十五分钟。

2 个答案:

答案 0 :(得分:1)

如果我理解你的要求:

SELECT [theView].CustomPollerAssignmentId
FROM
[theView]
LEFT JOIN
(
  SELECT CustomPollerAssignmentId, MAX([DateTime]) AS LastTime
  FROM [theView]
  WHERE [Status] <> 'IDLE' AND [DateTime] <= @Now
  GROUP BY CustomPollerAssignmentId
) AS NotIdleStatus ON
  [theView].CustomPollerAssignmentId = NotIdleStatus.CustomPollerAssignmentId
WHERE
  [theView].[DateTime] <= @Now AND
  [theView].[Status] = 'IDLE' AND
  (
    [theView].[DateTime] > NotIdleStatus.LastTime OR
    NotIdleStatus.LastTime IS NULL
  )
GROUP BY [theView].CustomPollerAssignmentId
  HAVING MIN([theView].[DateTime]) <= DATEADD(MINUTE, -10, @Now)    

这里的概念是

  1. 对于每个ID,选择非空闲状态的最新时间直到当前时间。
  2. 对于每个ID,请根据最近的非空闲时间加入空闲状态。
  3. 按ID分组状态。
  4. 过滤那些在10分钟前空闲的人。
  5. 同时过滤那些空闲时间晚于最新非空闲状态或没有非空闲状态的人。
  6. 以下代码选择每个ID的最后一次非空闲时间:

    SELECT CustomPollerAssignmentId, MAX([DateTime]) AS LastTime
    FROM [theView]
    WHERE [Status] <> 'IDLE' AND [DateTime] <= @Now
    GROUP BY CustomPollerAssignmentId
    

    我们正在使用LEFT JOIN,以便仍然捕获任何IDLE但从未处于任何其他状态的状态。 ON子句通过ID连接它们。

    以下代码选择空闲且在当前时间之前的代码:

    WHERE
      [theView].[DateTime] <= @Now AND
      [theView].[Status] = 'IDLE' AND ...
    

    以下代码按ID对记录进行分组,并选择最早时间早于当前时间前10分钟的ID:

    GROUP BY [theView].CustomPollerAssignmentId
      HAVING MIN([theView].[DateTime]) <= DATEADD(MINUTE, -10, @Now)    
    

    此外,您需要传递@Now值,这是您要检查的当前时间。

答案 1 :(得分:0)

SELECT v1.*
FROM (
    SELECT *
    FROM vdata
    WHERE OnlineStatus IN ('IDLE', 'DORMANT')
) v1
WHERE NOT EXISTS (
    SELECT 1
    FROM vdata v2
    WHERE v2.ModemId = v1.ModemId
    AND v2.MinuteMarker > v1.MinuteMarker 
    AND v2.MinuteMarker <= DATEADD(MINUTE, 10, v1.MinuteMarker )
    AND v2.OnlineStatus NOT IN ('IDLE', 'DORMANT')
)