T-SQL: найти значения последовательности, которые встречались ранее - PullRequest
0 голосов
/ 25 августа 2018

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

Spot Dir SeqCorr SeqAct moveID
------------------------------
 9    1    113    117    1085
 9    1    114    118    1086
 10   1    115    119    1087
 10   1    116    120    1088
 2    0    1      121    1089
 2    1    2      122    1090
 2    1    3      123    1091
 6    1    5      124    1092
 6    1    6      125    1093
 2    0    4      126    1094
 6    1    7      127    1095
 6    1    8      128    1096

Вопрос в том, как запросить данные, чтобы обнаружить случаи, когда Dir Спота = 0 (например, Spot2 с moveID = 1094), и Спот был посещен хотя бы один раз (MoveID с 1089 по 1091).

Выводом будет список moveID и другой столбец Status, показывающий ходы, которые являются возвратом к ранее посещенному Spot.

Status moveID
-------------
 0    1085
 0    1086
 0    1087
 0    1088
 0    1089
 0    1090
 0    1091
 0    1092
 0    1093
 1    1094
 0    1095
 0    1096

Ответы [ 3 ]

0 голосов
/ 25 августа 2018

Я подозреваю, что для робота нормально сидеть на одном месте для смежных ходов.Позднее проблема возвращается к более ранней точке.

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

select spot, min(moveid) as min_moveid, max(moveid) as max_moveid
from (select m.*,
             row_number() over (order by moveid) as seqnum,
             row_number() over (partition by spot order by moveid) as seqnum_s
      from moves m
     ) m
group by (seqnum - seqnum_s), spot;

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

Теперь задается вопрос о диапазоне перемещений для каждого пятна - появляется ли пятно более одного раза.Для этого теперь мы можем использовать count(*) в качестве оконной функции.Итак, чтобы получить вхождения дубликатов ходов:

with s as (
      select spot, min(moveid), max(moveid)
      from (select m.*,
                   row_number() over (order by moveid) as seqnum,
                   row_number() over (partition by spot order by moveid) as seqnum_s
            from moves m
           ) m
      group by (seqnum - seqnum_s), spot
     )
select s.*
from (select s.*,
             count(*) over (partition by spot) as cnt
      from s
     ) s
where cnt > 1;

Я считаю, что это отвечает на ваш вопрос.

0 голосов
/ 27 августа 2018

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

SELECT line, robot, min(moveid) moveIDmin, max(moveid) moveIDmax
        from (select m.*,
                     row_number() over (partition by line, robot order by moveid) as seqnum,
                     row_number() over (partition by line, robot, spot order by moveid) as seqnum_s
              from #Temp2 m
             ) m
        group by line, robot, (seqnum - seqnum_s), spot
        order by line, robot, moveIDmin

Полученный результат позволяет легко находить неэффективные ходы, например, в moveIDmin 298, где робот вернулся в ранее посещенное место.

   line  robot spot moveIDmin moveIDmax
  AER389X  G    26       1        72
  AER389X  G    30      73       137
  AER389X  J     2     138       139
  AER389X  J     6     140       224
  AER389X  J    10     225       297
  AER389X  J     6     298       301
  AER389X  J    14     302       319
  AER389X  K    14     320       380
  AER389X  K    18     381       468 
0 голосов
/ 25 августа 2018

Это даст вам все ходы, где место было посещено ранее для данного идентификатора

select m1.*
from moves m1
join moves m2 ON m1.spot = m2.spot and m1.moveID > m2.moveID
where m2.dir = 0

Это даст вам ходы, которые произошли подряд

select distinct m1.*
from moves m1
join moves m2 ON m1.spot = m2.spot and m1.dir = m2.dir and m1.moveID > m2.moveID
where m1.dir = 1
...