从使用(WHERE)条件选择的行中获取上一行和下一行

时间:2014-11-23 06:52:21

标签: sql sql-server sql-server-2012 rows

例如,我有这样的陈述:

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

此语句按字分割,如下表所示:

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

我希望得到每个单词的上一个和下一个单词

例如,我希望得到" name"的上一个和下一个单词:

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

我怎么能得到这个结果?

7 个答案:

答案 0 :(得分:33)

您没有指定DBMS,因此以下是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

答案 1 :(得分:7)

为什么没有身体给出简单的答案?

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

答案 2 :(得分:6)

没有子查询:

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

答案 3 :(得分:3)

使用Join获取SQL Server 2005加上的预期结果。

    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'

<强>结果:

enter image description here

Fiddler Demo

答案 4 :(得分:1)

试试这个

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`

答案 5 :(得分:1)

如果您希望选择快速,这是一种不同的方法。这需要一些准备工作。

  • 在数据库中创建一个包含单词的新列(例如“短语”) 你要。 (即前一个,当前和下一个)。

  • 写一个触发器,在插入时将新单词添加到上一个 行的短语并将前一行的单词添加到新行的单词并填充 短语。

  • 如果单个字词可以更改,您需要在更新时触发,以使短语保持同步。

然后只需选择短语。您可以获得更好的速度,但代价是额外的存储空间和更慢的插入速度以及更难的可维护性。显然你必须更新现有记录的短语列,但你有SQL在其他答案中这样做。

答案 6 :(得分:-1)

我在单词列上创建索引并设置此代码以快速获得结果:

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