MySQL GROUP BY DateTime +/- 3 seconds

后端 未结 5 1214
再見小時候
再見小時候 2020-12-03 05:34

Suppose I have a table with 3 columns:

  • id (PK, int)
  • timestamp (datetime)
  • title (text)

I have the following records:

         


        
5条回答
  •  爱一瞬间的悲伤
    2020-12-03 05:58

    Warning: Long answer. This should work, and is fairly neat, except for one step in the middle where you have to be willing to run an INSERT statement over and over until it doesn't do anything since we can't do recursive CTE things in MySQL.

    I'm going to use this data as the example instead of yours:

    id    Timestamp
    1     1:00:00
    2     1:00:03
    3     1:00:06
    4     1:00:10
    

    Here is the first query to write:

    SELECT a.id as aid, b.id as bid
    FROM Table a
    JOIN Table b 
    ON (a.Timestamp is within 3 seconds of b.Timestamp)
    

    It returns:

    aid     bid
    1       1
    1       2
    2       1
    2       2
    2       3
    3       2
    3       3
    4       4
    

    Let's create a nice table to hold those things that won't allow duplicates:

    CREATE TABLE
    Adjacency
    ( aid INT(11)
    , bid INT(11)
    , PRIMARY KEY (aid, bid) --important for later
    )
    

    Now the challenge is to find something like the transitive closure of that relation.

    To do so, let's find the next level of links. by that I mean, since we have 1 2 and 2 3 in the Adjacency table, we should add 1 3:

    INSERT IGNORE INTO Adjacency(aid,bid)
    SELECT adj1.aid, adj2.bid
    FROM Adjacency adj1
    JOIN Adjacency adj2
    ON (adj1.bid = adj2.aid)
    

    This is the non-elegant part: You'll need to run the above INSERT statement over and over until it doesn't add any rows to the table. I don't know if there is a neat way to do that.

    Once this is over, you will have a transitively-closed relation like this:

    aid     bid
    1       1
    1       2
    1       3     --added
    2       1
    2       2
    2       3
    3       1     --added
    3       2
    3       3
    4       4
    

    And now for the punchline:

    SELECT aid, GROUP_CONCAT( bid ) AS Neighbors
    FROM Adjacency
    GROUP BY aid
    

    returns:

    aid     Neighbors
    1       1,2,3
    2       1,2,3
    3       1,2,3
    4       4
    

    So

    SELECT DISTINCT Neighbors
    FROM (
         SELECT aid, GROUP_CONCAT( bid ) AS Neighbors
         FROM Adjacency
         GROUP BY aid
         ) Groupings
    

    returns

    Neighbors
    1,2,3
    4
    

    Whew!

提交回复
热议问题