Проблема с дублирующимся значением в базе данных (фильтрация на основе предыдущего значения) - PullRequest
1 голос
/ 25 сентября 2008

Ранее на этой неделе я задал вопрос о последовательной фильтрации повторяющихся значений во время выполнения. У меня были хорошие ответы, но объем данных, который я изучал, был медленным и неосуществимым.

В настоящее время в нашей базе данных значения событий не фильтруются. В результате дублируются значения данных (с разными временными метками). Нам необходимо обрабатывать эти данные во время выполнения и на уровне базы данных, поскольку они являются дорогостоящими (и не могут извлекать их в код, поскольку они часто используются в хранимых процессах), что приводит к увеличению времени запросов. Нам нужна структура данных, которую мы можем запросить, для которой это хранилище данных отфильтровано, поэтому дополнительная фильтрация во время выполнения не требуется.

В настоящее время в нашей базе данных

  • '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'

Это кажется тривиальным, но наша проблема в том, что мы получаем эти данные от беспроводных устройств, в результате чего получаются непоследовательные пакеты, а наш шлюз является многопоточным, поэтому мы не можем гарантировать, что полученные значения находятся в порядке. Что-то может войти как «1» в течение 4 секунд назад и «0» в течение 2 секунд назад, но мы обрабатываем «1» уже потому, что он был первым. Мы вращаем голову над тем, как реализовать это. Мы не можем сравнивать данные с последним значением в базе данных, потому что последние, возможно, на самом деле еще не поступили, поэтому, чтобы выбросить эти данные, мы были бы испорчены, и наша последовательность может быть полностью отключена. Таким образом, в настоящее время мы храним каждое входящее значение, и база данных переставляет себя в зависимости от времени ... но блоки могут отправлять 1,1,1,0, и оно действительно, потому что событие все еще активно, но мы хотим сохранить только включенное и выключенное состояние (первое появление включенного состояния 1,0,1,0,1,0) .. мы думали о триггере, но нам придется перетасовывать данные каждый раз, когда приходит новое значение, потому что оно может быть раньше, чем последнее сообщение, и это может изменить всю последовательность (вставка будет медленной).

Есть идеи?

Спросите, нужна ли вам дополнительная информация.

[EDIT] PK Не работает - проблема в том, что наши подразделения на самом деле отправляют разные временные метки. так что ПК не будет работать, потому что 1,1,1 одинаковы .. но есть разные метки времени. Подобное событие продолжалось в time1, событие все еще включалось в time2, оно отправляет нас обратно ... одно и то же значение в разное время.

Ответы [ 2 ]

1 голос
/ 25 сентября 2008

Если я правильно понимаю, то, что вы хотите сделать, это просто предотвратить попадание обманщиков в базу данных. Если это так, то почему бы не определить PK (или уникальный индекс) в первых двух столбцах, а база данных сделать тяжелую работу за вас. Двойные вставки будут неудачными в зависимости от PK или AK, которые вы определили. Ваш код (или сохраненный процесс) должен будет просто изящно обработать это исключение.

0 голосов
/ 25 сентября 2008

Вот решение для обновления. Производительность будет варьироваться в зависимости от индексов.

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

Нетрудно представить решение для фильтрации на основе этого. Это зависит только от того, как часто вы хотите искать предыдущую запись для каждой записи (каждый запрос или время от времени).

...