我有一张表格,其中包含以下内容
id timestamp
-------------------------------------
1 1247046037
4 1247047437
5 1247047438
6 1247048738
现在我想返回所有那些与之前的ID相隔3分钟的ID。在上面的例子中,它应该返回1,4,6。
我应该怎么做呢?有点困惑。我想尽可能地避免加入和其他所有事情。
更新抱歉,我忘了提及ID可能不是连续的,所以不能使用id = id + 1
答案 0 :(得分:2)
据我所知,如果没有加入,你将无法做到这一点。这应该做你需要的
select t1.id
from mytable as t1
left join mytable as t2 on t1.id = (t2.id + 1)
where t2.id is null or (t1.timestamp - 180) > t2.timestamp
如果id字段可能有间隙,则需要引入行号字段来执行此操作。如果你定期运行这个字段,可能会更有效地为你的表添加一个自动编号字段。
select t1.id
from
(select mytable.*, @rownum:=@rownum+1 as rownum from mytable, (select @rownum:=0) r order by id) as t1
left join
(select mytable.*, @rownum2:=@rownum2+1 as rownum from mytable, (select @rownum2:=0) r order by id) as t2 on t1.rownum = (t2.rownum + 1)
where t2.id is null or (t1.timestamp - 180) > t2.timestamp
答案 1 :(得分:1)
这在MSSQL中可以完美运行。看看MySQL是否可以处理这种打破平局的查询会很有趣:
SELECT curr.*
--//,prev.*
--//,curr."timestamp" - prev."timestamp"
FROM @Table curr
LEFT JOIN @Table prev
ON prev.ID = ( SELECT TOP 1 prev_match.ID
FROM @Table prev_match
WHERE prev_match.ID < curr.ID
ORDER BY prev_match.ID DESC)
WHERE curr."timestamp" - prev."timestamp" >= 180
OR prev.ID IS NULL --// cover special case when there is no previous at all
但是如果你离开而没有id=0
的行,我会从WHERE条件中移除OR并将LEFT JOIN
更改为INNER JOIN
答案 2 :(得分:0)
您可以使用null-self-join来获取彼此相邻的两个ID:
SELECT thing2.id
FROM things AS thing1
JOIN things AS thing2 ON thing1.id<thing2.id
LEFT JOIN things AS nothing ON nothing.id BETWEEN thing1.id+1 AND thing2.id-1
WHERE nothing.id IS NULL
AND thing2.timestamp=thing1.timestamp+180
即。在thing1和thing2之间没有id的行。
(这会产生相隔3分钟的行;从问题中不清楚你是否真的需要3分钟或3分钟或3分钟或更短的分钟行。)
答案 3 :(得分:0)
如果你想避免加入,我认为你可以使用子查询,但我希望它会更慢,所以建议不要使用它:
SELECT t.id
FROM yourTable t
WHERE t.timestamp -
(SELECT t3.timestamp --This gives the time of the id before
FROM yourTable t3
WHERE id =
(SELECT ISNULL(MAX(t2.id),-1) --This gives the id before or -1 if first id.
FROM yourTable t2
WHERE t2.id < t.id)
)
> 180