2011-11-04 9 views
5

mam ten scenariusz:SQL WHERE użyciem podobnych i porównując do pola

Chcę sprawdzić konkretne słowa, a jeśli pasuje termin, będę musiał aktualizować zawartość tej strony i połączyć go z termin. Ale na razie skupiam się na pozyskiwaniu stron z treścią, których część treści jest taka sama jak konkretne określenie.

To jest pomysł, co muszę zrobić, ale nie działa, ponieważ podzapytanie zwraca więcej niż jedno pole.

Chcę się dowiedzieć, GDZIE m.module_content jest JAKIEKOLWIEK z warunków, które mam, ale powinien sprawdzić je wszystkie.

SELECT m.module_termid, t.term_name, m.module_name, m.module_content 
FROM modules m 
JOIN terms t ON m.module_termid = t.term_id 
WHERE m.module_content LIKE '%' || (SELECT term_name FROM terms) || '%' 

module_content ma tekst w formacie HTML, więc w końcu wszystko to muszę zrobić to, czy pasuje termin i nie jest jeszcze linki, dodam link do tego konkretnego terminu.

Jaka jest najlepsza opcja tutaj? (Używam mysql btw)

Aby dać przykład, co spodziewany wynik jest:

Warunki: id: 1 Nazwa: hello modułów: ID: 1, treści: < p > Hello World </p>

chciałbym że moduły o identyfikatorze 1 doprowadza się do góry, ponieważ zawiera treści, które gdzieś ma nazwę termin „Hello”

aktualizacja:

sprawdzonym rozwiązaniem Pablo, ale to, co się dzieje:

enter image description here

„Ray Davis” nie ma nic wspólnego z pojęciem „pływać”, na przykład, tak że nie powinno pojawiły.

+0

Spróbujcie mojego podejścia wtedy :) –

Odpowiedz

5

Chyba po prostu trzeba zmienić swój stan JOIN coś jak:

SELECT m.module_termid, t.term_name, m.module_name, m.module_content 
    FROM modules m 
    JOIN terms t ON (m.module_content LIKE '%' || t.term_name || '%') 

Mimo, że to może być potencjalnie bardzo nieefektywne. Rozważ skorzystanie z INDEKSU PEŁNEGO TEKSTU INSTEAD dla tej operacji.

+0

Myślę, że daje to produkt kartezjański –

+0

To nie jest kompletny produkt kartezjański. Jest to sprzężenie warunku, który wygeneruje wiersze NxM ... A warunek dołączania powinien być tym, co chcesz: wszystkie wiersze, w których występuje termin w tablicy terminów wewnątrz 'module_content'. –

+0

Masz rację, idealnie to właśnie bym zrobił.Spójrz na przykładową odpowiedź, która pojawiła się (zwróć uwagę na to, że Doubleness Uprzejmości to termin, a

Ray Davis to

to treść, a to nie powinno pojawić się, dopóki nazwa tego terminu nie brzmi Ray Davis: Dzięki uprzejmości Double Up \t Ludzie, którzy Nie rozumiem Floating \t

Ray Davis

2

MySQL nie ma żadnego operatora konkatenacji, a zapytanie powinno być rzeczywiście zapisać jako:

SELECT m.module_termid, t.term_name, m.module_name, m.module_content 
    FROM modules m 
    JOIN terms t ON m.module_content LIKE CONCAT('%', t.term_name, '%'); 

Ale co się stało:

m.module_content LIKE '%' || t.term_name || '%' 

jest rzeczywiście równoważne

(m.module_content LIKE '%') || (t.term_name) || ('%') 

która zawsze wynosi 1.W ten sposób masz iloczyn kartezjański =)

UPD: więcej jako odniesienie do siebie, MySQL ma operatora konkatenacji ||, ale go używać należy ustawić PIPES_AS_CONCAT Tryb:

mysql> SET sql_mode= 'pipes_as_concat'; 
Query OK, 0 rows affected (0.00 sec) 

mysql> SELECT 'qwe' || 'asd'; 
+----------------+ 
| 'qwe' || 'asd' | 
+----------------+ 
| qweasd   | 
+----------------+ 
1 row in set (0.00 sec) 
4

Po trochę badań, moje rozwiązanie będzie wyglądać następująco:

SELECT m.module_termid, t.term_name, m.module_name, m.module_content 
    FROM modules m 
    INNER JOIN terms t ON m.module_termid = t.term_id 
    WHERE m.module_content LIKE CONCAT('%', TRIM(t.term_name), '%') 

edit: Odnośnie Paul Morgans komentarza, wymieniłem CONCAT('%', t.term_name, '%') z CONCAT('%', TRIM(t.term_name), '%') s o, że wszystkie białe spacje w t.term_name są usunięte. Jeśli potrzebne są spacje w t.term_name, po prostu usunąć wywołanie TRIM i używać starej wersji (CONCAT('%', t.term_name, '%'))

+0

+1, ale musisz przyciąć t.term_name w CONCAT, aby to działało poprawnie. nie musisz także żadnych spacji w t.term_name. –

0

Wypróbuj poniższe zapytanie -

SELECT 
    tp.module_termid, 
    tp.term_name, 
    tp.module_name, 
    tp.module_content 
FROM (
     SELECT 
      m.module_termid, 
      t.term_name, 
      m.module_name, 
      m.module_content, 
      IF(LOCATE(t.term_name,m.module_content)!=0, m.module_content, ' ') 
       as required_content 
     FROM modules m 
     LEFT JOIN terms t ON m.module_termid = t.term_id 
    ) tp 
WHERE tp.required_content != ''; 

Dla powyższego zapytania dostaniesz wszystkie wiersze gdzie term_name dane kolumn są obecne jako całe słowo w kolumnie module column_content column. Jeśli nie chcesz dopasowywać tylko całego wyrazu, wtedy możesz użyć funkcji wyrażeń regularnych MYSQL zamiast funkcji LOCATE.

Dokumentacja ZLOKALIZUJ funkcji można znaleźć na here

1

Możesz spróbować zamiast:

SELECT m.module_termid, t.term_name, m.module_name, m.module_content 
    FROM modules m 
    JOIN terms t ON (m.module_content LIKE '%' + t.term_name + '%') 
1

zamiast "LIKE", używając "IN" powinno być rozwiązanie: coś : -

SELECT m.module_termid, t.term_name, m.module_name, m.module_content
Z modułów m JOIN terms t ON m.module_termid = t.term_id
GDZIE m.module_content IN (WYBIERZ term nazwę z warunków);

0

Nie sądzę, że jest to dobry sposób rozwiązania tego problemu. Zaspiera to, że masz wiele elementów modułu, a popularnym słowem jest limit.ew czasie wykonywania sql, potrzebuje dużo dysku i może blokować online mysql db. Moja droga jest następująca:

  1. odwraca indeks zawartości modułu.
  2. wyszukaj popularne słowa z indeksem.
  3. powiązać identyfikator modułu ze słowem kluczowym.

jak widać. Jest bardzo wydajny i szybki. Problem polega na tym, jak zrobić odwrócony indeks na zawartości modułu. sphinx wykona dobrą robotę. mam nadzieję, że to ci pomoże :)