字段“自”和“至”放置在可随时更改的可逆列中

时间:2018-08-21 00:02:29

标签: sql oracle

这是我的餐桌之旅:

案例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。 如何更改查询以执行此操作?
预先感谢。

0 个答案:

没有答案