稍微复杂的mySQL查询

时间:2009-09-04 08:54:59

标签: sql mysql

我有一张表格,其中包含以下内容

id     timestamp
-------------------------------------
 1     1247046037
 4     1247047437
 5     1247047438
 6     1247048738

现在我想返回所有那些与之前的ID相隔3分钟的ID。在上面的例子中,它应该返回1,4,6。

我应该怎么做呢?有点困惑。我想尽可能地避免加入和其他所有事情。

更新抱歉,我忘了提及ID可能不是连续的,所以不能使用id = id + 1

4 个答案:

答案 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