2009-09-06 5 views
36

Ich habe 2 Tabellen, sagen Tabelle A und Tabelle B und ich möchte einen Join durchführen, aber die übereinstimmende Bedingung muss sein, wo eine Spalte von A 'wie' eine Spalte von B bedeutet, dass alles vor oder nach dem kommen kann Spalte in B:Wie benutzt man ein Like mit einem Join in sql?

zum Beispiel: wenn die Spalte in A 'foo' ist. Dann würde der Join übereinstimmen, wenn die Spalte in B entweder "Fooblah", "Something Fooblah" oder einfach "Foo" ist. Ich weiß, wie man die Wildcards in einer standardähnlichen Anweisung verwendet, aber ich bin verwirrt, wenn ich einen Join mache. Macht das Sinn? Vielen Dank.

Antwort

16

In MySQL können Sie versuchen:

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

Natürlich ist dies eine massiv ineffiziente Abfrage sein würde, weil es einen vollständigen Tabellenscan tun würde.

Update: Hier ist ein Beweis


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

Danke..wie würde ich die gleiche Funktionalität erreichen, aber es effizienter machen? –

+0

So würden Sie es tun. Wenn Sie es effizienter benötigen, können Sie das MYCOL-Feld in Tabelle B indizieren. –

+0

Wenn Sie den MyISAM-Tabellentyp verwenden, können Sie einen Volltextindex ausprobieren und sehen, ob das hilft. Im Allgemeinen ist die Volltextsuche jedoch keine Stärke von MySQL. Wenn die Volltextsuche ein zentraler Teil Ihrer Anwendung ist, sollten Sie Apache Lucene in Betracht ziehen - http://lucene.apache.org/java/docs/ – Asaph

63

Mit INSTR:

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

LIKE:

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

LIKE mit CONCAT:

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

Kenntnis, dass sich in allen Optionen, werden Sie wahrscheinlich für Groß- und Kleinschreibung, Sie werden immer Spiele ohne Sorge um sicherzustellen, vor dem Vergleich in Großbuchstaben die Spaltenwerte fahren wollen:

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 

Die effizienteste wird auf die hängt letztlich EXPLAIN plan Ausgabe.

JOIN Klauseln sind identisch mit Schreiben WHERE Klauseln. Die JOIN Syntax wird auch als ANSI-JOINs bezeichnet, da sie standardisiert waren. Nicht-ANSI-Joins wie folgt aussehen:

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

Ich bin nicht mit einem Nicht-ANSI-LEFT JOIN Beispiel gehen zu stören. Der Vorteil der ANSI JOIN-Syntax besteht darin, dass sie trennt, was zusammenfügende Tabellen miteinander verbindet, was tatsächlich in der WHERE-Klausel geschieht.

+0

Wie ist die beste Geschwindigkeit zwischen LIKE und INSTR für (zB Domainname)? – Meloman

5

Ist dies etwas, das Sie oft tun müssen, werde ... dann sollten Sie die Beziehung zwischen den Tabellen A und B.

Zum Beispiel denormalize, auf Einsatz Tabelle B, Sie Null schreiben könnte oder Weitere Einträge zu einer Juncion-Tabelle, die B auf A basierend auf partieller Zuordnung abbildet. In ähnlicher Weise können Änderungen an jeder Tabelle diese Zuordnung aktualisieren.

Dies hängt davon ab, wie häufig die Tabellen A und B geändert werden. Wenn sie ziemlich statisch sind, ist es weniger schmerzhaft, einen Treffer bei INSERT zu machen, als wiederholte Zugriffe auf SELECT.

+2

Das ist eine feine Lösung, aber es ist nicht korrekt, es Denormalisierung zu nennen. –

+2

Fair genug. Nennen Sie es dann eine Junction-Tabelle –

1

Die Verwendung von bedingten Kriterien in einem Join ist definitiv anders als die Where-Klausel. Die Kardinalität zwischen den Tabellen kann Unterschiede zwischen Joins und Where-Klauseln erzeugen.

Wenn Sie beispielsweise eine Like-Bedingung in einem Outer-Join verwenden, werden alle Datensätze in der ersten im Join aufgeführten Tabelle beibehalten.Wenn Sie dieselbe Bedingung in der Where-Klausel verwenden, wird die Verknüpfung implizit in eine innere Verknüpfung geändert. Der Datensatz muss im Allgemeinen in beiden Tabellen vorhanden sein, um den bedingten Vergleich in der Where-Klausel durchzuführen.

Ich verwende im Allgemeinen den Stil in einer der vorherigen Antworten gegeben.

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

Auf diese Weise kann ich den Join-Typ steuern.