我有一个对应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告诉我我的预期结果是否可行?
答案 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中的每一行发出了从属子查询。