T-SQL :找出之前出现的乱序值
T-SQL : find out of sequence values that have occurred before
这道题是关于找出乱序事件的,但仅限于之前发生过的事件。在下面的table个机器人动作数据中,每个动作都应该按顺序到相同或更高的点号,如果是这样,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(例如 Spot2 的 moveID = 1094)并且该 Spot 之前至少访问过一次(moveID 1089 到 1091)的情况。
输出将是一个 moveID 列表和另一个 Status 列,显示 return 到先前访问过的 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(*)
用作 window 函数。因此,要获得重复移动的出现:
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
这道题是关于找出乱序事件的,但仅限于之前发生过的事件。在下面的table个机器人动作数据中,每个动作都应该按顺序到相同或更高的点号,如果是这样,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(例如 Spot2 的 moveID = 1094)并且该 Spot 之前至少访问过一次(moveID 1089 到 1091)的情况。
输出将是一个 moveID 列表和另一个 Status 列,显示 return 到先前访问过的 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(*)
用作 window 函数。因此,要获得重复移动的出现:
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