2014-11-23 56 views
7

我有這樣的從(WHERE)的條件下選擇的行獲取先前和下一行

例如表我有這樣的說法:

my name is joseph and my father name is brian 

此語句由分詞這樣的表

------------------------------ 
|  ID  | word  | 
------------------------------ 
|  1  |  my  | 
|  2  |  name | 
|  3  |  is  | 
|  4  |  joseph | 
|  5  |  and  | 
|  6  |  my  | 
|  7  |  father | 
|  8  | name  | 
|  9  |  is  | 
|  10  | brian | 
------------------------------ 

我想獲得相同的字

的前面和後面的值。例如我想獲得「名稱」的上一個和下一個單詞:

-------------------------- 
| my | name | is | 
-------------------------- 
| father | name | is | 
-------------------------- 

我該怎麼做?

+1

你的ID有沒有差距? – plalx 2014-11-23 06:59:35

+2

你使用什麼數據庫?你使用的是哪個版本的數據庫? SQL是一種語言,但幾乎每個數據庫都支持一種略有不同的SQL方言。當你使用一個支持像'lead'和'lag'這樣的分析函數的數據庫時,這種事情就容易多了。 – 2014-11-23 07:03:55

+0

我使用SQL 2012,支持LAG和LEAD,但我希望快速獲得500萬字的結果,其重要的是在我的程序中以非常快的速度取得結果 – 2014-11-24 04:54:58

回答

13

你沒有指定你的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

+0

,在內部select語句中整個表的行是結合在一起的,在外面:選擇具有相同單詞的行,如果我只需要一個單詞,則所有表單詞被合併,然後選擇它們中的一個... – 2014-11-24 05:04:07

+0

其確定,但是我有超過1億個記錄,並且時間去取結果非常重要,我可以提高此代碼的性能嗎 – 2014-11-24 05:11:41

+0

我想快速得到結果,你能幫我嗎? – 2014-11-24 09:18:34

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` 
+0

它可以,但我有超過1億條記錄,是非常重要的,我可以提高代碼的性能嗎? – 2014-11-24 05:21:13

3

無子查詢:

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 
+0

如果id序列中存在空白,則這將不起作用 – 2014-11-24 10:46:44

+0

@ t-clausen.dk op表示該表是從分割句子創建的,所以不應該有任何與此代碼的差距 – Will 2014-11-24 16:31:52

1

如果您希望選擇速度更快,這是一種不同的方法。它需要一些準備工作。

  • 在將包含 你想要的話數據庫中創建一個新的列(例如「詞組」)。 (即前一個,當前和下一個)。

  • 寫一個觸發器,在插入追加新詞前面 行的短語,並預置上一行的字新行的字和填補 短語。

  • 如果單個單詞可以更改,則需要更新觸發器才能使短語保持同步。

然後只選擇短語。你獲得更好的速度,但需要額外的存儲和更慢的插入和更難以維護。很明顯,您必須更新現有記錄的短語列,但是您有SQL可以在其他答案中執行此操作。

1

使用Join可獲得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' 

結果:

enter image description here

Fiddler Demo

-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 
+0

請勿將標識符用作有意義的字段 – 2015-03-13 10:39:55

1

爲什麼沒有-b ody給出簡單的答案?

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

您無法將結果限制爲下一個/上一個一個特定的詞。接受的答案有一個'WHERE'子句。 – Gili 2018-01-07 08:02:10