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

StackOverflow https://stackoverflow.com/questions/134049

Вопрос

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

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

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

  • '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)..мы подумывали о триггере, но нам пришлось бы перетасовывать данные каждый раз, когда поступало новое значение, потому что оно могло быть раньше последнего сообщения и это могло изменить всю последовательность (вставки были бы медленными).

Есть какие-нибудь идеи?

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

[РЕДАКТИРОВАТЬ] PK не будет работать - проблема в том, что наши устройства фактически отправляют разные временные метки.таким образом, PK не будет работать, потому что 1,1,1 - это одно и то же..но там разные временные метки.Подобное событие произошло во время time1, событие все еще продолжается во время time2, оно отправляет нас обратно и то, и другое..одно и то же значение в разное время.

Это было полезно?

Решение

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

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