2008-08-21 18 views
10

Kann/Soll ich ein LIKE-Kriterium als Teil eines INNER JOIN beim Erstellen einer gespeicherten Prozedur/Abfrage verwenden? Ich bin mir nicht sicher, ob ich das Richtige verlange, also lass es mich erklären.Verwenden Sie eine LIKE-Klausel in einem INNEREN JOIN

Ich erstelle eine Prozedur, die eine Liste der zu suchenden Schlüsselwörter in einer Spalte mit Text enthält. Wenn ich an der Konsole saß, würde ich es als solche auszuführen:

SELECT Id, Name, Description 
    FROM dbo.Card 
WHERE Description LIKE '%warrior%' 
     OR 
     Description LIKE '%fiend%' 
     OR 
     Description LIKE '%damage%' 

Aber ein Trick, den ich eine Weile gehen abgeholt zu tun „stark typisierte“ -Liste Parsen in eine gespeicherte Prozedur, die Liste zu analysieren ist in eine Tabellenvariable/temporäre Tabelle, wandle sie in den richtigen Typ um und mache dann einen INNEREN JOIN gegen diese Tabelle in meiner endgültigen Ergebnismenge. Dies funktioniert hervorragend, wenn Sie eine Liste von Integer-IDs an die Prozedur senden. Ich habe eine endgültige Abfrage, die wie folgt aussieht:

SELECT Id, Name, Description 
    FROM dbo.Card 
     INNER JOIN @tblExclusiveCard ON dbo.Card.Id = @tblExclusiveCard.CardId 

Ich möchte diesen Trick mit einer Liste von Zeichenfolgen verwenden. Aber da ich nach einem bestimmten Schlüsselwort suche, werde ich die LIKE-Klausel verwenden. Idealerweise denke ich, dass meine letzte Abfrage so aussehen würde:

Ist das möglich/empfohlen?

Gibt es einen besseren Weg, so etwas zu tun?


Der Grund Ich setze Wildcards an beiden Enden der Klausel ist, weil es „archfiend“, „Tier-Krieger“, „Direkt Schaden“ und „Kampf-Schaden“ Begriffe, die in verwendet werden, die Kartentexte.

Ich habe den Eindruck, dass ich abhängig von der Leistung entweder die angegebene Abfrage verwenden oder eine Volltext-Stichwortsuche verwenden kann, um die gleiche Aufgabe zu erfüllen?

Abgesehen davon, dass der Server einen Textindex für die Felder erstellt, für die ich eine Textsuche durchführen möchte, muss ich noch etwas anderes tun?

Antwort

4

Ihre erste Abfrage funktioniert, erfordert jedoch einen vollständigen Tabellenscan, da jeder Index für diese Spalte ignoriert wird. Sie müssen auch einige dynamische SQL machen, um alle Ihre LIKE-Klauseln zu generieren.

Versuchen Sie eine Volltextsuche, wenn Sie SQL Server verwenden oder eine der Lucene Implementierungen auschecken. Joel sprach kürzlich von seinem Erfolg.

1

Es scheint, als ob Sie nach Volltextsuche suchen. Weil Sie eine Reihe von Schlüsselwörtern gegen die Kartenbeschreibung abfragen und Treffer finden wollen? Richtig?

1

Persönlich habe ich es vorher gemacht, und es hat gut für mich gearbeitet. Die einzigen Probleme, die ich sehen konnte, sind möglicherweise Probleme mit einer nicht indizierten Spalte, aber ich denke, dass Sie das gleiche Problem mit einer Where-Klausel haben.

Mein Rat an Sie ist nur Blick auf die Ausführungspläne zwischen den beiden. Ich bin mir sicher, dass es je nach Situation besser sein wird, wie alle guten Programmierprobleme.

0

Die Leistung hängt vom tatsächlichen Server ab, den Sie verwenden, sowie vom Schema der Daten und der Datenmenge. Mit aktuellen Versionen von MS SQL Server sollte diese Abfrage problemlos ausgeführt werden (MS SQL Server 7.0 hatte Probleme mit dieser Syntax, aber it was addressed in SP2).

Haben Sie diesen Code über einen Profiler ausgeführt? Wenn die Leistung schnell genug ist und die Daten über die entsprechenden Indizes verfügen, sollten Sie alle Einstellungen vornehmen.

0

LIKE '% Fiend%' wird nie eine Suche verwenden, wie 'Teufel%' wird. Einfach eine Platzhaltersuche ist nicht sargable

1

@Dillie-O
Wie groß ist diese Tabelle?
Was ist der Datentyp des Feldes Beschreibung?

Wenn beide klein sind, wird eine Volltextsuche übertrieben sein.

@ Dillie-O
Vielleicht haben Sie nicht die Antwort, wo der Suche nach, aber ich würde eine Schemaänderung befürworten ...

vorgeschlagene Schema:

create table name(
    nameID identity/int 
    ,name varchar(50)) 

create table description(
    descID identity/int 
    ,desc varchar(50)) --something reasonable and to make the most of it alwase lower case your values 

create table nameDescJunc(
    nameID int 
    ,descID int) 

Dieses Sie ohne verwenden Index des lassen haben um eine Lösung zu implementieren, und hält Ihre Daten atomar.

bezogen werden: Recommended SQL database design for tags or tagging

1

ein Trick, den ich ein wenig aufgenommen, während gehen zu tun „stark typisierte“ -Liste Parsing in eine gespeicherte Prozedur ist die Liste in eine Tabelle Variable/temporäre Tabelle zu analysieren

denke ich, was Sie hier anspielen könnte ist die Schlüsselwörter in einen Tisch schließen dann relational division Streichhölzer zu finden (auch eine andere Tabelle für Wörter auszuschließen verwenden könnte). Für ein funktionierendes Beispiel in SQL siehe Keyword Searches by Joe Celko.

0

Versuchen Sie dies;

SELECT Id, Name, Description 
FROM dbo.Card 
INNER JOIN @tblKeyword ON dbo.Card.Description LIKE '%' + 
           CONCAT(CONCAT('%',@tblKeyword.Value),'%') + '%' 
3

Versuchen Sie, diese

select * from Table_1 a 
    left join Table_2 b on b.type LIKE '%' + a.type + '%' 

Diese Praxis ist nicht ideal. Verwenden Sie mit Vorsicht.

+2

ich denke, das 'CONCAT sein sollte ('%', a.type, '%')' http.: //stackoverflow.com/a/23276513/443900 – Lee

0

versuchen es ...

select * from table11 a inner join table2 b on b.id like (select '%'+a.id+'%') where a.city='abc'. 

Seine Werke für mich :-)