mysql自我加入最小的差异

时间:2013-07-20 15:23:11

标签: mysql sql join self-join

我有一个对应SQL / Mysql连接操作的问题。

我的数据库表结构包含以下字段

  

时间戳

     

lat double

     

lon double

所以实际数据看起来像这样

  

| 2013-07-20 16:32:22 | 49.3 | 8.3 |

     

| 2013-07-20 16:17:09 | 49.2 | 8.2 |

     

| 2013-07-20 15:58:19 | 49.1 | 8.1 |

我现在想要将此表与其自身连接,以便一个数据集与具有下一个较低时间戳的数据集连接。因此,两者之间的区别很小。

所以最后我的结果将是

  

| 2013-07-20 16:32:22 | 49.3 | 8.3 | 2013-07-20 16:17:09 | 49.2 | 8.2 |

     

| 2013-07-20 16:17:09 | 49.2 | 8.2 | 2013-07-20 15:58:19 | 49.1 | 8.1 |

为了达到目的,我尝试了下面的SQL语句

  

SELECT * FROM position p1,position p2 WHERE p1.time> p2.time GROUP BY p1.time;

但是结果并不完全是我想要的,这个解决方案没有正确地对'secound(分组)部分进行排序。它看起来像这样:

  

| 2013-07-20 16:32:22 | 49.3 | 8.3 | 2013-07-20 15:58:19 | 49.1 | 8.1 |

     

| 2013-07-20 16:17:09 | 49.2 | 8.2 | 2013-07-20 15:58:19 | 49.1 | 8.1 |

有人可以通过SQL告诉我我的预期结果是否可行?

2 个答案:

答案 0 :(得分:1)

这确实是可能的。不幸的是,MySQL缺少使这很容易的功能。

我会对行进行排名,然后按等级加入:

select 
  p1.time as time1,
  p1.lat as lat1,
  p1.lon as lon1,
  p1.rank as rank1,
  p2.time as time2,
  p2.lat as lat2,
  p2.lon as lon2,
  p2.rank as rank2
from (
  select position.*,
    @curRank1 := @curRank1 + 1 AS rank 
  from position , (SELECT @curRank1 := 0) r 
  order by time desc) p1
join (
  select position.*,
    @curRank2 := @curRank2 + 1 AS rank 
  from position , (SELECT @curRank2 := 0) r 
  order by time desc) p2
on p1.rank = p2.rank -1

这是表明它在行动的小提琴:http://sqlfiddle.com/#!2/d777f/8

答案 1 :(得分:1)

在我看来,这也是一种更具“可读性”的可能性:

select 
  p1.time as time1,
   (select min(p2.time) as time2
    from position p2
    where p2.time > p1.time)
from position p1

但请注意,这种可读性带有二次复杂性,因为子查询将针对p1的每一行执行。如果你的表足够大,你应该使用jtseng的代码。

PS:Sqlfiddle查看查询计划:http://sqlfiddle.com/#!2/d777f/10

PPS:包含其他字段可能如下所示:

select 
  p1.time as time1,
  p1.lat as lat1,
  p1.lon as lon1,
  p2.time as time2,
  p2.lat as lat2,
  p2.lon as lon2
from
  position p1,
  position p2
where
  p2.time = (select min(p.time)
   from position p
   where p.time > p1.time)

更好的可读性,但也为p1中的每一行发出了从属子查询。