2009-09-06 11 views
36

Mam 2 tabele, powiedzmy tabelę A i tabelę B i chcę wykonać łączenie, ale warunek dopasowania musi być tam, gdzie kolumna od A 'jest jak "kolumna z B, co oznacza, że ​​wszystko może nadejść przed lub po kolumna w B:Jak korzystać z podobnych do sprzężenia w sql?

na przykład: jeśli kolumna w A jest "foo". Wtedy sprzężenie byłoby zgodne, jeśli kolumna w B jest albo: "fooblah", "somethingfooblah", albo po prostu "foo". Wiem, jak używać symboli wieloznacznych w standardowej instrukcji, ale jestem zdezorientowany podczas łączenia. Czy to ma sens? Dzięki.

Odpowiedz

16

W MySQL można spróbować:

SELECT * FROM A INNER JOIN B ON B.MYCOL LIKE CONCAT('%', A.MYCOL, '%');

Oczywiście byłoby to masywnie nieefektywne kwerendy, ponieważ byłoby to zrobić pełne skanowanie tabeli.

Aktualizacja: Oto dowód


create table A (MYCOL varchar(255)); 
create table B (MYCOL varchar(255)); 
insert into A (MYCOL) values ('foo'), ('bar'), ('baz'); 
insert into B (MYCOL) values ('fooblah'), ('somethingfooblah'), ('foo'); 
insert into B (MYCOL) values ('barblah'), ('somethingbarblah'), ('bar'); 
SELECT * FROM A INNER JOIN B ON B.MYCOL LIKE CONCAT('%', A.MYCOL, '%'); 
+-------+------------------+ 
| MYCOL | MYCOL   | 
+-------+------------------+ 
| foo | fooblah   | 
| foo | somethingfooblah | 
| foo | foo    | 
| bar | barblah   | 
| bar | somethingbarblah | 
| bar | bar    | 
+-------+------------------+ 
6 rows in set (0.38 sec) 
+1

Dzięki ... czy uzyskam tę samą funkcjonalność, ale sprawię, że będzie bardziej wydajna? –

+0

Tak właśnie można to zrobić. Jeśli chcesz, aby był bardziej wydajny, możesz indeksować pole MYCOL na tabeli B. –

+0

Jeśli używasz typu tabeli MyISAM, możesz wypróbować indeks pełnotekstowy i sprawdzić, czy to pomaga. Generalnie jednak, przeszukiwanie całego tekstu nie jest siłą MySQL. Jeśli wyszukiwanie pełnotekstowe jest podstawową częścią aplikacji, rozważ coś takiego jak Apache Lucene - http://lucene.apache.org/java/docs/ – Asaph

63

Korzystanie INSTR:

SELECT * 
    FROM TABLE a 
    JOIN TABLE b ON INSTR(b.column, a.column) > 0 

Używanie takich jak:

SELECT * 
    FROM TABLE a 
    JOIN TABLE b ON b.column LIKE '%'+ a.column +'%' 

Używanie LIKE, z CONCAT:

SELECT * 
    FROM TABLE a 
    JOIN TABLE b ON b.column LIKE CONCAT('%', a.column ,'%') 

uwadze, że we wszystkich opcji, prawdopodobnie będziesz chciał pojechać wartości kolumny na wielkie przed porównaniem do zapewnienia otrzymujesz mecze bez troski o wielkości liter:

SELECT * 
    FROM (SELECT UPPER(a.column) 'ua' 
     TABLE a) a 
    JOIN (SELECT UPPER(b.column) 'ub' 
     TABLE b) b ON INSTR(b.ub, a.ua) > 0 

Najskuteczniejszym będzie zależeć ostatecznie na EXPLAIN plan wyjście.

JOIN Klauzule są identyczne z klauzulami WHERE. Składnia JOIN jest również określana jako ANSI JOIN, ponieważ zostały one znormalizowane. Non-ANSI JOIN wyglądać następująco:

SELECT * 
    FROM TABLE a, 
     TABLE b 
WHERE INSTR(b.column, a.column) > 0 

nie będę się przejmować o przykład dla ANSI LEFT JOIN. Zaletą składni ANSI JOIN jest to, że oddziela ona to, co łączy tabele, od tego, co faktycznie dzieje się w klauzuli WHERE.

+0

Jaka jest najlepsza prędkość między LIKE i INSTR (np. Nazwa domeny)? – Meloman

5

Jeśli jest to coś trzeba robić często ... to może chcesz denormalize relacji między tabelami A i B.

Na przykład, na wkładce do tabeli B, można napisać do zera lub więcej wpisów do tablicy tabel odwzorowania B do A na podstawie mapowania częściowego. Podobnie zmiany w obu tabelach mogą zaktualizować to powiązanie.

Wszystko zależy od tego, jak często tabele A i B są modyfikowane. Jeśli są dość statyczne, wtedy trafienie na INSERT jest mniej bolesne, niż powtarzające się trafienia w SELECT.

+2

To jest dobre rozwiązanie, ale nie można tego nazwać denormalizacją. –

+2

Wystarczająco fair. Nazwij to wtedy stołem skrzyżowania –

1

Stosowanie kryteriów warunkowych w złączeniu zdecydowanie różni się od klauzuli Where. Liczność między tabelami może tworzyć różnice między klauzulami Połączenia i Gdzie.

Na przykład użycie warunku Like w połączeniu zewnętrznym spowoduje zachowanie wszystkich rekordów w pierwszej tabeli wymienionej w łączeniu.Użycie tego samego warunku w klauzuli Where spowoduje niejawną zmianę sprzężenia z łączeniem wewnętrznym. Rekord musi być na ogół obecny w obu tabelach, aby wykonać porównanie warunkowe w klauzuli Where.

Generalnie używam stylu podanego w jednej z wcześniejszych odpowiedzi.

tbl_A as ta 
    LEFT OUTER JOIN tbl_B AS tb 
      ON ta.[Desc] LIKE '%' + tb.[Desc] + '%' 

W ten sposób mogę kontrolować typ łączenia.

Powiązane problemy