簡體   English   中英

T-SQL:查找之前發生的亂序值

[英]T-SQL : find out of sequence values that have occurred before

這個問題與查找亂序事件有關,但僅查找之前發生的事件。 在下表中的機器人動作數據中,每個動作應依次到達相同或更高的點號,如果為真,則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

問題是我將如何查詢數據以檢測Spot的Dir = 0(例如,具有moveID = 1094的Spot2)和Spot至少被訪問過一次(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

這將為您提供給定ID之前曾參觀過景點的所有舉動

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

我懷疑機器人可以坐在一個位置上進行相鄰移動很好。 問題稍后將返回到較早的位置。

如果是這樣,這就是一個空白與孤島問題的例子。 當機器人在給定位置上時,可以通過使用不同的行號來解決該問題以獲取相鄰的移動:

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;

我相信這可以回答您的問題。

這是該問題的最終解決方案。 這次,我基於更大的數據集添加了分區和分組,這些數據集涵蓋了不同生產線和制造工廠不同部門中的機器人。

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 

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM