T-SQL:查找以前发生过的顺序错误值
这个问题与查找无序事件有关,但只查找以前发生过的事件。在下表的机器人移动数据中,每个移动都应按顺序指向相同或更高的点编号,如果为真,则DIR方向=1。正确的序列已预先编程为SeqCorr,实际序列已记录为SeqAct以供比较T-SQL:查找以前发生过的顺序错误值,sql,tsql,sql-server-2014,Sql,Tsql,Sql Server 2014,这个问题与查找无序事件有关,但只查找以前发生过的事件。在下表的机器人移动数据中,每个移动都应按顺序指向相同或更高的点编号,如果为真,则DIR方向=1。正确的序列已预先编程为SeqCorr,实际序列已记录为SeqAct以供比较 Spot Dir SeqCorr SeqAct moveID ------------------------------ 9 1 113 117 1085 9 1 114 118 1086 10 1 115
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(如moveID=1094的Spot2)以及该点在moveID 1089到1091之前至少访问过一次的情况 输出将是一个moveID列表和另一个状态列,显示返回到以前访问过的地点的移动
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
你怎么知道之前和之后发生了什么?在关系数据库中,表是无序的,因此除非您有一个列可以按顺序使用,如创建日期或标识列,否则无法知道记录的前后。此外,样本数据最好作为+。请将您的问题包括在内,包括您当前的尝试和期望的结果。如moveID=1094的Spot2,并且在moveID 1089到1091之前,该Spot至少被访问过一次,您所说的之前发生的事件的所有序列和ID都大于之后发生的事件的序列和ID。你是倒数还是我遗漏了什么?谢谢Zohar,是的,moveID充当了一个标识列。为了更清楚地了解stick bit的要求,移动次数会随着时间的推移而增加,因此在moveID 1094处返回第2点是在最初3次访问第2点后,moveID为1089到1091。推测第6点是另一个例子,但是9和10不是。你应该解释一下这种差异。谢谢你。你能回答一个问题吗minmoveID和maxmoveID应该在哪里使用???@FyllSee。我应该给他们取个别名,但是当一个点被连续占据时,他们会显示移动的范围。这将显示范围的一行,而不是每个移动的单独一行。您可以使用join、exists或in获取原始行,但我发现这种表示方式通常更方便。