本周早些时候,我问了一个有关在运行时按顺序过滤掉重复值的问题。有一些很好的答案,但我要处理的数据量很慢而且不可行。

目前在我们的数据库中,事件值未被过滤。导致重复的数据值(具有不同的时间戳)。我们需要在运行时处理这些数据,并且在数据库级别处理这些数据的时间成本很高(并且无法将其提取到代码中,因为它在存储过程中大量使用),从而导致查询时间较长。我们需要一个可以查询的数据结构,该数据结构已过滤掉该数据存储,以便在运行时不需要额外的过滤。

目前在我们的数据库中

  • 'F07331E4-26EC-41B6-BEC5-002AACA58337', '1', '2008-05-08 04:03:47.000'
  • 'F07331E4-26EC-41B6-BEC5-002AACA58337', '0', '2008-05-08 10:02:08.000'
  • 'F07331E4-26EC-41B6-BEC5-002AACA58337', '0', '2008-05-09 10:03:24.000' (需要删除此)**
  • 'F07331E4-26EC-41B6-BEC5-002AACA58337', '1', '2008-05-10 04:05:05.000'

我们需要的

  • 'F07331E4-26EC-41B6-BEC5-002AACA58337', '1', '2008-05-08 04:03:47.000'
  • 'F07331E4-26EC-41B6-BEC5-002AACA58337', '0', '2008-05-08 10:02:08.000'
  • 'F07331E4-26EC-41B6-BEC5-002AACA58337', '1', '2008-05-10 04:51:05.000'

这看起来微不足道,但我们的问题是,我们从无线设备获取这些数据,导致数据包无序,而且我们的网关是多线程的,因此我们无法保证获得的值是有序的。某些内容可能会在 4 秒前出现“1”,在 2 秒前出现“0”,但我们已经处理了“1”,因为它是第一个出现的。我们一直在思考如何实施这一点。我们无法将数据与数据库中的最新值进行比较,因为最新值实际上可能还没有进来,因此如果将这些数据扔掉,我们就会被搞砸,我们的序列可能会完全偏离。因此,目前我们存储传入的每个值,并且数据库根据时间自行洗牌。但单元可以发送 1,1,1,0 及其有效,因为事件仍然处于活动状态,但我们只想存储开和关状态(第一次出现开状态 1,0,1,0,1, 0)..我们考虑了一个触发器,但每次有新值出现时,我们都必须对数据进行洗牌,因为它可能早于最后一条消息,并且它可以更改整个序列(插入会很慢)。

有任何想法吗?

询问您是否需要任何进一步的信息。

[编辑] PK 不起作用 - 问题是我们的单位实际上发送不同的时间戳。所以 PK 不起作用,因为 1,1,1 是相同的..但有不同的时间戳。就像事件在时间 1 发生,事件在时间 2 仍然发生,它把我们都发回了..相同的值不同的时间。

有帮助吗?

解决方案

这是一个更新解决方案。性能会根据索引的不同而有所不同。

DECLARE @MyTable TABLE
(
  DeviceName varchar(100),
  EventTime DateTime,
  OnOff int,
  GoodForRead int
)

INSERT INTO @MyTable(DeviceName, OnOff, EventTime)
SELECT 'F07331E4-26EC-41B6-BEC5-002AACA58337', 1, '2008-05-08 04:03:47.000' 
INSERT INTO @MyTable(DeviceName, OnOff, EventTime)
SELECT 'F07331E4-26EC-41B6-BEC5-002AACA58337', 0, '2008-05-08 10:02:08.000' 
INSERT INTO @MyTable(DeviceName, OnOff, EventTime)
SELECT 'F07331E4-26EC-41B6-BEC5-002AACA58337', 0, '2008-05-09 10:03:24.000'
INSERT INTO @MyTable(DeviceName, OnOff, EventTime)
SELECT 'F07331E4-26EC-41B6-BEC5-002AACA58337', 1, '2008-05-10 04:05:05.000' 

UPDATE mt
SET GoodForRead = 
CASE
  (SELECT top 1 OnOff
   FROM @MyTable mt2
   WHERE mt2.DeviceName = mt.DeviceName
     and mt2.EventTime < mt.EventTime
   ORDER BY mt2.EventTime desc
  )
  WHEN null THEN 1
  WHEN mt.OnOff THEN 0
  ELSE 1
END
FROM @MyTable mt
    -- Limit the update to recent data
--WHERE EventTime >= DateAdd(dd, -1, GetDate())

SELECT *
FROM @MyTable

不难想象基于此的过滤解决方案。这仅取决于您想要查找每条记录的前一条记录的频率(每次查询或偶尔一次)。

其他提示

如果我理解正确的话,您想要做的只是防止受骗者进入数据库。如果是这种情况,为什么不在前两列上定义 PK(或唯一索引)并让数据库为您完成繁重的工作。根据您定义的 PK 或 AK,重复插入会失败。然后,您的代码(或存储过程)只需优雅地处理该异常即可。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top