Get previous and next row from rows selected with (WHERE) conditions

a 夏天 提交于 2019-12-17 15:43:21

问题


For example I have this statement:

my name is Joseph and my father's name is Brian

This statement is splitted by word, like this table:

------------------------------
|      ID      |   word      |
------------------------------
|       1      |   my        |
|       2      |   name      |
|       3      |   is        |
|       4      |   Joseph    |
|       5      |   and       |
|       6      |   my        |
|       7      |   father's  |
|       8      |   name      |
|       9      |   is        |
|       10     |   Brian     |
------------------------------

I want to get previous and next word of each word

For example I want to get previous and next word of "name":

--------------------------
|    my    |  name  |  is |
--------------------------
| father's |  name  |  is |
--------------------------

How could I get this result?


回答1:


you didn't specify your DBMS, so the following is ANSI SQL:

select prev_word, word, next_word
from (
    select id, 
           lag(word) over (order by id) as prev_word,
           word,
           lead(word) over (order by id) as next_word
    from words
) as t
where word = 'name';

SQLFiddle: http://sqlfiddle.com/#!12/7639e/1




回答2:


Why did no-body give the simple answer?

SELECT LAG(word) OVER ( ORDER BY ID ) AS PreviousWord ,
       word ,
       LEAD(word) OVER ( ORDER BY ID ) AS NextWord
FROM   words;



回答3:


Without subqueries:

SELECT a.word 
FROM my_table AS a
JOIN my_table AS b 
ON b.word = 'name' AND abs(a.id - b.id) <= 1
ORDER BY a.id



回答4:


Use Join to get the expected result for SQL Server 2005 plus.

    create table words (id integer, word varchar(20));

    insert into words
    values
    (1 ,'my'),
    (2 ,'name'),
    (3 ,'is'),
    (4 ,'joseph'),
    (5 ,'and'),
    (6 ,'my'),
    (7 ,'father'),
    (8 ,'name'),
    (9 ,'is'),
    (10,'brian');

SELECT A.Id ,  C.word AS PrevName , 
               A.word AS CurName , 
               B.word AS NxtName 
FROM words AS A
LEFT JOIN words AS B ON A.Id = B.Id - 1
LEFT JOIN words AS C ON A.Id = C.Id + 1
WHERE A.Word = 'name'

Result:

Fiddler Demo




回答5:


Try this

SELECT *
FROM   tablename a
WHERE  ID IN(SELECT ID - 1
             FROM   tablename 
             WHERE  word = 'name') -- will fetch previous rows of word `name` 
        OR ID IN(SELECT ID + 1
                 FROM   tablename 
                 WHERE  word = 'name') -- will fetch next rows of word `name`
        OR word = 'name' -- to fetch the rows where word = `name`



回答6:


Here's a different approach, if you want the selects to be fast. It takes a bit of preparation work.

  • Create a new column (e.g. "phrase") in the database that will contain the words you want. (i.e. the previous, the current and next).

  • Write a trigger that on insert appends the new word to the previous row's phrase and prepends the previous row's word to the new row's word and fills phrase.

  • If the individual words can change, you'll need a trigger on update to keep the phrase in sync.

Then just select the phrase. You get much better speed, but at the cost of extra storage and slower insert and harder maintainability. Obviously you have to update the phrase column for the existing records, but you have the SQL to do that in the other answers.




回答7:


I create index on my words column and set this code to get result quickly:

WITH CTE AS 
(SELECT * FROM WordsTable WHERE word=N'Name')
SELECT          
    t2.word AS previousWord,
    t1.word,
    t3.word AS nextWord
FROM
    WordsTable AS t2,
    CTE AS t1,
    WordsTable AS t3
WHERE
    (t2.ID + 1)= t1.ID AND
    (t3.ID - 1) = t1.ID


来源:https://stackoverflow.com/questions/27086377/get-previous-and-next-row-from-rows-selected-with-where-conditions

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!