2012-04-26 8 views
8

następujące dwa zdania:SQL lewo samosprzężenie z GDZIE zależności klauzula między dwiema kopiami tabeli

hello there 
bye! 

są reprezentowane w sentence_words stołowych przez:

WORD_ID SENTENCE_ID WORD WORD_NUMBER 
10  1    hello 1 
11  1    there 2 
12  2    bye! 1 

chcę zrobić zapytanie zewnętrzne, które daje mi wyniki:

WORD1  WORD2 
hello  there 
bye!  NULL 

Pamiętaj, że mogę zacząć od środka o f zdanie, więc nie można zakładać, że słowo2 ma word_number = 2. Jeśli wybiorę my_start_number = 2, to zapytanie może dać mi:

WORD1 WORD2 
there NULL 

Próbowałem:

(my_start_number = 1) 

select s1.word word1, s2.word word2 
from sentence_words s1 
left join sentence_words s2 
on s1.sentence_id = s2.sentence_id 
where s1.word_number = my_start_number 
and (s2.word_number = s1.word_number +1 or s2.word_number is null); 

To tylko daje mi wynik jeśli w zdaniu są dwa słowa. Nie jestem pewien, co zrobić, to nie jest skomplikowane.

+0

Co to są za pomocą mssql, mysql, oracel? – Arion

+0

Czy próbujesz odtworzyć zdanie lub jesteś zainteresowany powrotem par słów? –

Odpowiedz

10

Przeniesienie wymogu word_number + 1 do LEFT JOIN.

SELECT 
    s1.word word1, s2.word word2 
FROM 
    sentence_words s1 
LEFT JOIN 
    sentence_words s2 
    ON s2.sentence_id = s1.sentence_id 
    AND s2.word_number = s1.word_number + 1 
WHERE 
    s1.word_number = my_start_number 
+0

Brilliant - Działa idealnie. – user984003

1

Odpowiedź Dems jest absolutnie poprawna. Postanowiłem napisać tę odpowiedź, aby wyjaśnić, dlaczego oryginalne rozwiązanie nie działa. To dlatego, że starają się odfiltrować następujący zestaw wyników lewej outter join (pokazując wszystkie kolumny, a niektóre nazwy skrócone, aby dopasować):

s1.WORD_ID s1.SENT_ID s1.WORD s1.WORD_NUM s2.WORD_ID s2.SENT_ID s2.WORD s2.WORD_NUM 
10   1   hello 1   10   1   hello 1 
10   1   hello 1   11   1   there 2 
11   1   there 2   10   1   hello 1 
11   1   there 2   11   1   there 2 
12   2   bye!  1   12   2   bye!  1 

Teraz spójrz na swojej klauzuli WHERE:

where s1.word_number = my_start_number 
and (s2.word_number = s1.word_number +1 or s2.word_number is null); 

... i powinno być stosunkowo łatwo zobaczyć, dlaczego to nie działa. Na przykład s2.word_number nigdy nie jest NULL.