SELECT N rows before and after the row matching the condition?

前端 未结 6 1728
暗喜
暗喜 2021-02-02 15:02

The behaviour I want to replicate is like grep with -A and -B flags . eg grep -A 2 -B 2 \"hello\" myfile.txt will give me all the lines wh

相关标签:
6条回答
  • 2021-02-02 15:38

    Right, this works for me:

    SELECT child.*
    FROM stack as child,
    (SELECT idstack FROM stack WHERE message LIKE '%hello%') as parent
    WHERE child.idstack BETWEEN parent.idstack-2 AND parent.idstack+2;
    
    0 讨论(0)
  • 2021-02-02 15:39

    Try this simple one (edited) -

    CREATE TABLE messages(
      id INT(11) DEFAULT NULL,
      message VARCHAR(255) DEFAULT NULL
    );
    
    INSERT INTO messages VALUES 
      (1, 'One tow three'),
      (2, 'No error in this'),
      (3, 'My testing message'),
      (4, 'php module test'),
      (5, 'hello world'),
      (6, 'team spirit'),
      (7, 'puzzle game'),
      (8, 'social game'),
      (9, 'stackoverflow'),
      (10, 'stackexchange');
    
    SET @text = 'hello world';
    
    SELECT id, message FROM (
      SELECT m.*, @n1:=@n1 + 1 num, @n2:=IF(message = @text, @n1, @n2) pos
        FROM messages m, (SELECT @n1:=0, @n2:=0) n ORDER BY m.id
    ) t
    WHERE @n2 >= num - 2 AND @n2 <= num + 2;
    
    +------+--------------------+
    | id   | message            |
    +------+--------------------+
    |    3 | My testing message |
    |    4 | php module test    |
    |    5 | hello world        |
    |    6 | team spirit        |
    |    7 | puzzle game        |
    +------+--------------------+
    

    N value can be specified as user variable; currently it is - '2'.

    This query works with row numbers, and this guarantees that the nearest records will be returned.

    0 讨论(0)
  • 2021-02-02 15:47

    Don't know if this is at all valid MySQL but how about

    SELECT  t.* 
    FROM    theTable t
            INNER JOIN (
              SELECT id FROM theTable where message like '%hello%'
            ) id ON id.id <= t.id
    ORDER BY
            ID DESC
    LIMIT   3                    
    UNION ALL 
    SELECT  t.* 
    FROM    theTable t
            INNER JOIN (
              SELECT id FROM theTable where message like '%hello%'
            ) id ON id.id > t.id
    ORDER BY
            ID
    LIMIT   2
    
    0 讨论(0)
  • 2021-02-02 15:47

    Try

    Select * from theTable
    Where id >=
    (Select id - variableHere from theTable where message like '%hello%')
    Order by id
    Limit (variableHere * 2) + 1
    
    0 讨论(0)
  • 2021-02-02 15:50

    (MS SQL Server only)

    The most reliable way would be to use the row_number function that way it doesn't matter if there are gaps in the id. This will also work if there are multiple occurances of the search result and properly return two above and below each result.

    WITH
    
    srt AS (
        SELECT ROW_NUMBER() OVER (ORDER BY id) AS int_row, [id]
        FROM theTable
    ),
    
    result AS (
        SELECT int_row - 2 AS int_bottom, int_row + 2 AS int_top
        FROM theTable
            INNER JOIN srt
                ON theTable.id = srt.id
        WHERE ([message] like '%hello%')
    )
    
    SELECT theTable.[id], theTable.[message]
    FROM theTable
        INNER JOIN srt
            ON theTable.id = srt.id
        INNER JOIN result
            ON srt.int_row >= result.int_bottom
            AND srt.int_row <= result.int_top
    ORDER BY srt.int_row
    
    0 讨论(0)
  • 2021-02-02 15:58

    Adding an answer using date instead of an id. The use-case here is an on-call rotation table with one record pr week. Due to edits the id might be out of order for the purpose intended. Any use-case having several records pr week, pr date or other will of course have to be mended.

    +----------+--------------+------+-----+---------+----------------+
    | Field    | Type         | Null | Key | Default | Extra          |
    +----------+--------------+------+-----+---------+----------------+
    | id       | int(11)      | NO   | PRI | NULL    | auto_increment |
    | startdate| datetime     | NO   |     | NULL    |                |
    | person   | int(11)      | YES  | MUL | NULL    |                |
    +----------+--------------+------+-----+---------+----------------+
    

    The query:

    SELECT child.*
    FROM rota-table as child,
     (SELECT startdate
        FROM rota-table
        WHERE YEARWEEK(startdate, 3) = YEARWEEK(now(), 3) ) as parent
    WHERE
        YEARWEEK(child.startdate, 3) >= YEARWEEK(NOW() - INTERVAL 25 WEEK, 3)
        AND YEARWEEK(child.startdate, 3) <= YEARWEEK(NOW() + INTERVAL 25 WEEK, 3)
    
    0 讨论(0)
提交回复
热议问题