2014-11-23 6 views
7

Ich habe eine Tabelle wie dieSetzen Sie sich mit (WO) Bedingungen ausgewählt vorherige und nächste Zeile aus Reihen

Zum Beispiel habe ich diese Aussage haben:

my name is joseph and my father name is brian 

Diese Aussage Wort wie dieser Tabelle aufgespalten wird

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

ich mag vorherigen und nächsten Wert von demselben Wort

zum Beispiel bekommen Ich möchte das vorherige und nächste Wort "Name" erhalten:

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

Wie kann ich das tun?

+1

Gibt es Lücken in Ihren IDs? – plalx

+2

Welche Datenbank benutzen Sie? Welche Version dieser Datenbank verwenden Sie? SQL ist eine Sprache, aber fast jede Datenbank hat einen etwas anderen Dialekt von SQL, den sie unterstützt. Dies ist viel einfacher, wenn Sie eine Datenbank verwenden, die analytische Funktionen wie "Lead" und "Lag" unterstützt. –

+0

Ich benutze SQL 2012, Unterstützung LAG und LEAD, aber ich möchte Ergebnis für 5 Millionen Wort schnell nehmen, ist es wichtig, Ergebnis sehr schnell in meinem Programm zu nehmen –

Antwort

13

Sie nicht Ihre DBMS angeben, so dass die folgenden 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

mit diesem Code sein sollte, in inner Select-Anweisung das ganze Zeilen der Tabelle sind kombinieren und in äußeren: Wählen Sie Zeilen mit dem gleichen Wort, wenn ich nur ein Wort nehmen alle Tabellenwörter kombiniert werden sollen und dann wählen Sie eine von ihnen ... –

+0

ist in Ordnung, aber ich habe über 100 Millionen Datensätze und Zeit, um Ergebnis zu nehmen, ist sehr wichtig, kann ich die Leistung dieses Codes verbessern –

+0

Ich möchte Ergebnis schnell erhalten, können Sie mir helfen? –

1

Versuchen Sie, diese

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

Es ist ok, aber ich habe mehr als 100 Millionen Datensätze und Zeit zu nehmen Ergebnis ist sehr wichtig, kann ich die Leistung von Code verbessern? –

3

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

dies funktioniert nicht, wenn es Lücken in der ID-Sequenz gibt –

+0

@ t-clausen.dk op sagte die Tabelle wurde aus dem Aufteilen eines Satzes erstellt, so dass es keine Lücke – Will

1

Hier ist ein anderer Ansatz, wenn Sie möchten, dass die Auswahl schnell ist. Es braucht ein wenig Vorbereitungsarbeit.

  • Erstellen Sie eine neue Spalte (zum Beispiel „Phrase“) in der Datenbank, die die Wörter Sie enthalten wird. (d. h. der vorherige, der aktuelle und der nächste).

  • schreiben einen Trigger, dass am Einsatz an der vorherigen Zeile der Begriff das neue Wort anhängt und prepends das Wort des vorherigen Zeile das Wort des neuen Zeile und füllt Phrase.

  • Wenn sich die einzelnen Wörter ändern können, benötigen Sie einen Auslöser für das Update, um die Phrase synchron zu halten.

Dann wählen Sie einfach die Phrase. Sie erhalten viel bessere Geschwindigkeit, aber auf Kosten von zusätzlichem Speicher und langsamer Einfügung und härterer Wartbarkeit. Offensichtlich müssen Sie die Phrasespalte für die vorhandenen Datensätze aktualisieren, aber Sie haben die SQL, um das in den anderen Antworten zu tun.

1

Verwenden Sie Join, um das erwartete Ergebnis für SQL Server 2005 plus zu erhalten.

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' 

Ergebnis:

enter image description here

Fiddler Demo

-1

I Index auf meine Worte Spalte erstellen und diesen Code eingestellt schnell Ergebnisse zu erhalten:

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

Verwenden Sie keine Kennungen als sinnvolle Felder –

1

Warum hat Nein-b ody die einfache Antwort geben?

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

Sie können Ergebnisse nicht auf nächste/vorherige von beschränken ein bestimmtes Wort. Die akzeptierte Antwort enthält eine WHERE-Klausel. – Gili