这是我的餐桌之旅:
案例1:始终从Chkpt1移到Chkpt2
Journey HHMM Chkpt1 Chkpt2
41 1600 AAA BBB
41 1601 AAA BBB
41 1602 AAA BBB
41 1603 CCC DDD
41 1603 BBB CCC
41 1604 DDD EEE
点Chkpt1和Chkpt2定义了一条道路的路段。在这种情况下,车辆经过41段,即AAA-BBB,BBB-CCC,CCC-DDD,DDD-EEE。
我的问题:我需要获得旅程的第一和最后一点,以及它们各自的时间。对于这种情况1,答案是:
Journey ChkptStart Time1 ChkptEnd Time2
41 AAA 1600 EEE 1604
要考虑此问题,需要考虑以下几点:
1)每分钟跟踪一次轨迹。这样可以生成具有相同检查点的多行。
2)跟踪每个段。如果车辆在同一分钟内从一个路段移动到另一个路段,则同一分钟内可以插入多条线-它们可以按任何顺序出现(CCC-DDD出现在BBB-CCC之前)。
3)最棘手的点-在每一行中,车辆不一定从Chkpt1移动到Chkpt2。它可能正在从Chkpt2移到Chkpt1。问题是如何推导实际方向(此表上没有“方向”列,因此不能更改该表)。
案例2:始终从Chkpt2迁移到Chkpt1
Journey HHMM Chkpt1 Chkpt2
42 1700 YYY ZZZ
42 1701 YYY ZZZ
42 1702 WWW XXX
42 1702 XXX YYY
42 1702 VVV WWW
42 1703 UUU VVV
In this case, the vehicle is moving from ZZZ to UUU and the answer is
Journey ChkptStart Time1 ChkptEnd Time2
42 ZZZ 1700 UUU 1703
情况3:结合从Chkpt1到Chkpt2以及从Chkpt2到Chkpt1的运动
Journey HHMM Chkpt1 Chkpt2
43 2100 PPP QQQ
43 2101 PPP QQQ
43 2102 PPP QQQ
43 2103 SSS RRR
43 2103 QQQ RRR
43 2104 SSS TTT
这意味着:
从21:00到21:02,车辆进入PPP到QQQ(从Chkpt1到Chkpt2)。
在21:03,去QQQ到RRR(从Chkpt1到Chkpt2)。
在21:03,它将去往SSS(从Chkpt2到Chkpt1)的RRR。
在21:04,它到达SSS到TTT(从Chkpt1到Chkpt2)。
因此,我们不再有限制,即汽车始终从Chkpt1行驶到Chkpt2,或者总是从Chkpt2行驶到Chkpt1。这可以从一个细分变为另一个细分。
所需结果:
Journey ChkptStart Time1 ChkptEnd Time2
43 PPP 2100 TTT 2104
段始终以相同的顺序表示。曾经被表示为WWW-XXX的网段以后将无法由XXX-WWW表示。
我一直在使用以下解决方案(由Clockwork-Muse提出)。 对于我的原始问题(Building a query for a table whose fields From and To are placed in reversible columns),这是案例1和案例2的绝佳解决方案。
WITH Deduplicated AS (SELECT id, checkpoint1, checkpoint2, MIN(hhmm) as startTime, MAX(hhmm) as endTime
FROM Journey
GROUP BY id, checkpoint1, checkpoint2),
Path (id, originPoint, originStartTime, originEndTime, checkpoint2, startTime, endTime, lev)
AS (SELECT id, checkpoint1, startTime, endTime, checkpoint2, startTime, endTime, 0
FROM Deduplicated
WHERE NOT EXISTS (SELECT 1
FROM Journey b
WHERE b.id = Deduplicated.id
AND b.checkpoint2 = Deduplicated.checkpoint1)
UNION ALL
SELECT Path.id, Path.originPoint, Path.originStartTime, Path.originEndTime,
Deduplicated.checkpoint2, Deduplicated.startTime, Deduplicated.endTime, lev + 1
FROM Path
JOIN Deduplicated
ON Deduplicated.id = Path.id
AND Deduplicated.checkpoint1 = Path.checkpoint2)
SELECT id,
CASE WHEN originStartTime > startTime
OR originEndTime > endTime
THEN checkPoint2
ELSE originPoint END AS checkpointStart,
LEAST(originStartTime, startTime) AS time1,
CASE WHEN originStartTime > startTime
OR originEndTime > endTime
THEN originPoint
ELSE checkPoint2 END AS checkpointEnd,
GREATEST(originEndTime, endTime) AS endTime
FROM (SELECT Path.*, MAX(lev) OVER(PARTITION BY id) AS lim
FROM Path) Filtered
WHERE lev = lim
问题一:
现在我需要针对案例3进行修改。
问题二:
此查询不会返回仅包含一个细分的旅程。例如:
Journey HHMM Chkpt1 Chkpt2
45 0900 RRR SSS
45 0901 RRR SSS
45 0902 RRR SSS
所需结果:
Journey ChkptStart Time1 ChkptEnd Time2
45 RRR 0900 SSS 0902
查询似乎至少需要两个段,因此它可以建立从第一段到第二段的连接。实际上,只有一条记录,我们无法确定哪个是起点和终点。
在这种情况下,我们可以考虑将汽车移至Chkpt1至Chkpt2。
如何更改查询以执行此操作?
预先感谢。