【问题标题】:Slightly complex mySQL Query稍微复杂的 mySQL 查询
【发布时间】:2009-09-04 08:54:58
【问题描述】:

我有一张桌子,里面有以下内容

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

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

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

更新对不起,我忘了说 ID 可能不是连续的,所以不能使用 id = id+1

【问题讨论】:

    标签: sql mysql


    【解决方案1】:

    据我所知,如果没有连接,您将无法做到这一点。这应该可以满足您的需要

    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
    

    【讨论】:

      【解决方案2】:

      这将在 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

      【讨论】:

      • ‘TOP 1’ 是 MSSQL 特有的语法; MySQL 和 Postgres 的版本最后是“LIMIT 1”。但不幸的是,MySQL 不能限制子查询。
      • 你能在子查询中改用SELECT MAX(prev_match.ID) ...吗?
      【解决方案3】:

      您可以使用 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 分钟或更少分钟的行。)

      【讨论】:

        【解决方案4】:

        如果你想避免加入,我认为你可以使用子查询,但我希望它会更慢,所以建议不要这样做:

        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
        

        【讨论】:

          猜你喜欢
          • 2014-05-14
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2012-11-20
          • 1970-01-01
          相关资源
          最近更新 更多