数据库重复值问题(基于先前的值进行过滤)

时间:2020-03-06 14:43:41  来源:igfitidea点击:

本周早些时候,我问一个有关在运行时按顺序过滤出重复值的问题。虽然有一些好的答案,但是我要遍历的数据量太慢且不可行。

当前在我们的数据库中,事件值未过滤。结果是重复的数据值(带有不同的时间戳)。我们需要在运行时处理该数据,并在数据库级别对其进行处理,这将导致代价高昂的查询时间(并且无法将其拉入代码,因为它在存储的proc中使用了很多)。我们需要一个可以查询的数据结构,该数据结构已过滤掉该数据存储,以便在运行时不需要其他过滤。

目前在我们的数据库中

  • '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发生,它将不同的时间发送回给我们。

解决方案

如果我理解正确,那么我们要做的就是防止重复对象进入数据库。如果是这样,为什么不在前两列中定义PK(或者唯一索引),并让数据库为我们完成繁重的工作。根据我们定义的PK或者AK,重复插入将失败。然后,我们就是代码(或者存储的proc),只需优雅地处理该异常即可。

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

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

不难想象基于此的过滤解决方案。它仅取决于我们要查找每个记录的上一个记录的频率(每次查询或者不定期查询)。