2015-05-26 3 views
0

Я делал много чтения о островах данных и суммировал их с помощью CTE или множества подзапросов. Большинство, похоже, полагается на умную математику с датой, которая выглядит круто, но я не думаю, что это сработает для меня.Обобщение данных Острова

У нас есть много регистраторов данных о транспортных средствах, отправляющих статусные обновления в разных расписаниях. Я ищу более быстрый, не-петлевый способ суммирования определенных статусов.

  • NodeId Идентификатор устройства
  • LOGID Запись журнала PK
  • AssembledTime Когда запись была собрана на устройстве
  • ReceivedTime Когда запись была получена на сервере
  • Скорость Скорость при t IME каротажа
  • Может его статуса содержат несколько ключевых слов

Данные обычно обрабатываются в конце поездки. (зажигание на зажигание выключено) Существует LogTrips, что обеспечивает NodeId, StartTime и EndTime. В настоящее время я просматриваю записи журнала, упорядоченные по AssembledTime, и ищу StatusText, например% any%. Я делаю это несколько раз, исходя из предпочтительных статусов клиентов. например: (StatusText, например «% ремня безопасности%» или StatusText, например «% s/b%») и lm.Speed> 10, для людей, движущихся без ремня безопасности

После некоторого чтения я вижу, что могу использовать row_number (), чтобы создать правильную последовательную запись, и извлечь статусы хотели, используя случай, когда ... конец

SELECT RowNumber = ROW_NUMBER() OVER(ORDER BY l.AssembledTime), 
      l.NodeId, 
      l.LogId, 
      l.AssembledTime, 
      lm.Speed, 
      lm.StatusText, 
      StatusSpeed = CASE WHEN lm.StatusText like '%speed%' THEN 1 ELSE 0 END, 
      StatusAccident = CASE WHEN lm.StatusText like '%accident%' THEN 1 ELSE 0 END, --impact? 
      StatusSeatbeltDriving = CASE WHEN (lm.StatusText like '%seatbelt%' or lm.StatusText like '%s/b%') and lm.Speed > 10 THEN 1 ELSE 0 END, 
      StatusSeatbeltIdle = CASE WHEN (lm.StatusText like '%seatbelt%' or lm.StatusText like '%s/b%') and lm.Speed = 0 THEN 1 ELSE 0 END, 
      Status4wd = CASE WHEN (lm.StatusText like '%4wd%' or lm.StatusText like '%4x4%') THEN 1 ELSE 0 END 

    FROM Ctrack6.dbo.Logs l 
    JOIN Ctrack6.dbo.LogMobiles lm on l.LogId = lm.LogId 
    WHERE l.NodeId = @NodeId 
    AND  l.AssembledTime between @TripStart AND @TripEnd 

Это даст мне список всех журналов для поездки устройств, в следующей последовательности:

RowNumber NodeId LogId AssembledTime Speed StatusText StatusSpeed StatusAccident StatusSeatbeltDriving StatusSeatbeltIdle Status4wd IsProcessed 
1 3099 308815155 2015-05-26 11:05:43.000 0 Start up 0 0 0 0 0 0 
2 3099 308815156 2015-05-26 11:05:55.000 0 Driving 0 0 0 0 0 0 
3 3099 308815157 2015-05-26 11:06:25.000 10 Driving 0 0 0 0 0 0 
4 3099 308815158 2015-05-26 11:06:45.000 11 Driving 0 0 0 0 0 0 
5 3099 308815344 2015-05-26 11:07:15.000 0 Driving 0 0 0 0 0 0 
6 3099 308815345 2015-05-26 11:07:16.000 0 Seatbelt 0 0 0 1 0 0 
7 3099 308815477 2015-05-26 11:07:19.000 0 Seatbelt 0 0 0 1 0 0 
8 3099 308815479 2015-05-26 11:07:24.000 0 Seatbelt 0 0 0 1 0 0 
9 3099 308815481 2015-05-26 11:07:29.000 0 Seatbelt 0 0 0 1 0 0 
10 3099 308815482 2015-05-26 11:07:34.000 0 Seatbelt 0 0 0 1 0 0 
11 3099 308815598 2015-05-26 11:07:39.000 0 Seatbelt 0 0 0 1 0 0 
12 3099 308815599 2015-05-26 11:07:44.000 0 Seatbelt 0 0 0 1 0 0 
13 3099 308815600 2015-05-26 11:07:49.000 0 Seatbelt 0 0 0 1 0 0 
14 3099 308815601 2015-05-26 11:07:54.000 0 Seatbelt 0 0 0 1 0 0 
15 3099 308815729 2015-05-26 11:08:00.000 0 Seatbelt 0 0 0 1 0 0 
16 3099 308815730 2015-05-26 11:08:05.000 0 Seatbelt 0 0 0 1 0 0 
17 3099 308815731 2015-05-26 11:08:10.000 0 Seatbelt 0 0 0 1 0 0 
18 3099 308815732 2015-05-26 11:08:15.000 0 Seatbelt 0 0 0 1 0 0 
19 3099 308816439 2015-05-26 11:08:45.000 0 Seatbelt 0 0 0 1 0 0 
20 3099 308816440 2015-05-26 11:09:15.000 0 Seatbelt 0 0 0 1 0 0 
21 3099 308816441 2015-05-26 11:09:45.000 0 Seatbelt 0 0 0 1 0 0 
22 3099 308816442 2015-05-26 11:10:07.000 0 Ignition off 0 0 0 0 0 0 

Желаемые результаты суммируют строки 6-21. С

  • NodeId - NodeId устройства
  • StartLogId LOGID рядка 6
  • EndLogId LOGID рядка 21
  • EventStartTime AssembledTime рядка 6
  • EventEndTime Собранное время строки 21
  • типСобытия «Seatbelt»

Если бы было несколько островов, было бы несколько резюме

Я просто не получаю то, что я мог бы группировать по сделать свои острова.

ответ

0

Я нашел решение на следующей странице: https://www.simple-talk.com/sql/t-sql-programming/the-sql-of-gaps-and-islands-in-sequences/

Более конкретно:

Добавлено две Табличные переменные

declare @logs table 
(
    LogId int PRIMARY KEY, 
    RowNumberAll int, 
    RowNumberNode int, 
    NodeId int, 
    AssembledTime datetime, 
    Speed int, 
    StatusText varchar(200), 
    StatusSpeed bit, 
    StatusAccident bit, 
    StatusSeatbeltDriving bit, 
    StatusSeatbeltIdle bit, 
    Status4wd bit, 
    UNIQUE(Nodeid, RowNumberNode), 
    UNIQUE(RowNumberAll) 
) 

declare @results table 
(
    EventType varchar(50), 
    NodeId int, 
    StartSeqNo int, 
    EndSeqNo int, 
    LogCount int, 
    UNIQUE(NodeId, StartSeqNo, EventType) 
) 

Добавлен дополнительный столбец RowNumberNode для запроса.

RowNumberNode = ROW_NUMBER() OVER(PARTITION BY NodeId ORDER BY l.AssembledTime), 

Изменен пример для работы с моим кодом. У меня есть 1 из этих блоков для каждого состояния, я хочу, чтобы sunmarised

INSERT INTO @results (EventType, NodeId, StartSeqNo, EndSeqNo, LogCount) 
SELECT 'Speed', 
    NodeId, 
    StartSeqNo=MIN(RowNumberNode),  
    EndSeqNo=MAX(RowNumberNode), 
    LogCount=MAX(RowNumberNode) - MIN(RowNumberNode) + 1 
FROM 
(
    SELECT NodeId, 
      RowNumberNode, 
      rn=RowNumberNode-ROW_NUMBER() OVER (PARTITION BY NodeId  ORDER BY RowNumberNode) 
    FROM @logs 
    WHERE StatusSpeed=1 
) a 
GROUP BY NodeId, rn 
--HAVING MIN(RowNumberNode) - MAX(RowNumberNode) > 0 
ORDER BY NodeId, StartSeqNo; 
0

Что именно я могу группировать?

Как я сделать это флаг каждого «изменение состояния» с 1. Тогда я нарастающим итогом на этом поле. Это дает вам уникальный уникальный номер для каждой группы, которую вы можете группировать.

Лично я всегда загружать эти вещи в промежуточную таблицу для обработки, а не пытаться использовать кучу встроенных подзапросов по двум причинам:

  1. По разным причинам это часто быстрее (вы можете создать специальные индексы, позволяет оптимизировать размер данных)
  2. вы можете добавить множество дополнительных «помощника» колонок, которые позволяют отлаживать эту заведомо сложную обработку (т.е. отображение бесплатный текстовый комментарий к известному статуса)

Кроме того, находясь в постановка та BLE вы можете использовать конструкции, как это «сожрать» остров:

SELECT 1 

WHILE @@ROWCOUNT<> 0 
BEGIN 

    UPDATE TGT 
    SET ChangeColumn=1 
    FROM YourTable TGT 
    INNER JOIN YourTable PriorRow 
    WHERE PriorRow.RowNum-1 = TGT.RowNum 
    AND PriorRow.State = TGT.State 
    AND ChangeColumn=0 

END 

Если запустить это он продолжает работать, пока все изменения состояний не будут найдены и помечены

+0

Я попытался запустить это за сутки (371444 строк). Не вернулся через час, поэтому я убил его. – Hecatonchires

+0

Похоже, вы уже нашли свое решение. В любом случае для 371 444 строк, я предполагаю, что существует бесконечный цикл, и логика в UPDATE должна быть исправлена, так как она должна прекратить обновление, когда это не требуется. –

Смежные вопросы