2012-08-08 5 views
6

Ich habe eine Website, wo ich in der Lage sein muss, nach Daten zu suchen und die Abfrage alle Anführungszeichen ignorieren zu lassen.SQL Server - Gibt es eine einfache Möglichkeit, Angebote bei der Suche zu ignorieren?

  1. Suche nach nicht, nicht oder nicht und die Ergebnisse für die Zeilen abzurufen, die Wörter, die mit beginnen: nicht, nicht oder nicht
  2. Suche nach „Hallo“ oder „Hallo“ oder hallo und abrufen von Ergebnissen für Zeilen, die haben Wörter, die mit beginnen: „Hallo“, „Hallo“ oder hallo

Anmerkung: Ich bin schon Strippen die Angebote für die in das Suchwort übergeben

Ich möchte zu wissen, ob es eine einfache (oder weniger ausführlich) ist Methode als:

select Name 
    from tbl_MyTable 
where (Replace(Replace(Replace(Replace(Replace(Replace(Name,'“',''),'‘',''),'''',''),'"',''),'’',''),'”','') like 'dont%' 
    or Replace(Replace(Replace(Replace(Replace(Replace(Name,'“',''),'‘',''),'''',''),'"',''),'’',''),'”','') like '% dont%'); 

Gerade jetzt, meine beste Idee ist es, eine neue Spalte zu erstellen das enthält die Zitat-gestrippt Version (mit einem Leerzeichen vorangestellt), so dass ich nur tun kann:

select Name 
    from tbl_MyTable 
where FixedName like '% dont%'; 

Aber ich würde wirklich gerne wissen, ob dies ohne die Schaffung eine neue Spalte erreicht werden kann und es effizient sein.

+0

Ich Frage von einer C# -App, so gibt es ein wenig Beinarbeit, die auf dieser Seite getan werden kann, aber nicht auf Kosten der Leistung. Mein Code fragt tatsächlich mehrere Tabellen und Spalten ab (ich habe den Fall hier einfach vereinfacht), daher möchte ich am liebsten eine Datenbereichs-Antwort. –

Antwort

1

einen Volltextindex Verwenden Sie statt LIKE.

Erstellen Sie Ihre Volltext-Index:

http://msdn.microsoft.com/en-us/library/ms187317.aspx

CREATE UNIQUE INDEX ix1 ON tbl_MyTable(YourKey); //unique index required 
CREATE FULLTEXT CATALOG ft AS DEFAULT; // ft is your freetext catalog name 
CREATE FULLTEXT INDEX ON tbl_MyTable(Name) 
    KEY INDEX ix1 
    WITH STOPLIST = SYSTEM; // this is your index and allows you to run the command below 

Dann ist diese benutzen, um Ihre Abfrage auszuführen:

SELECT Name 
FROM tbl_MyTable 
WHERE FREETEXT(Name, 'dont'); 

Das ist die schnellste Methode für diese Art der Sache. Sie können sogar noch schneller werden, wenn Sie Freitext-Engines von Drittanbietern verwenden, aber das ist wahrscheinlich nicht nötig.

+0

So wäre die Lösung: 1) Erstellen Sie die Spalte FixedName, die die Anführungszeichen entfernt. 2) Erstellen Sie den Volltextindex für die Spalte FixedName. 3) ... 4) Gewinn? –

+0

Nein, Sie müssen die Anführungszeichen nicht entfernen. Erstellen Sie einfach Ihren Volltextindex für die Namensspalte. Ich habe meine Antwort aktualisiert, um dies zu berücksichtigen. –

0

würde ich vorschlagen, eine benutzerdefinierte Funktion zu schaffen, diese Logik zu konsolidieren:

CREATE FUNCTION [dbo].[udf_StripQuotes] 
(
    @String VARCHAR(MAX) 
) 
RETURNS VARCHAR(MAX) 
AS 
BEGIN 
    RETURN Replace(
     Replace(
      Replace(
       Replace(
        Replace(
         Replace(@String,'“',''), 
        '‘',''), 
       '''',''), 
      '"',''), 
     '’',''), 
    '”','') 
END 
GO 

die dann wie folgt aussieht:

select Name 
from tbl_MyTable 
where dbo.udf_StripQuotes(name) like '% dont%'; 

Soweit Effizienz, die Vorder- und Hinter % in Ihrer like Aussage verhindert, dass Sie Indizes verwenden, was zu einem vollständigen Tabellenscan führt ... Dies ist wahrscheinlich der größte Leistungseinbruch bei dieser Abfrage.

Wie Aaron jedoch klarstellt, wird diese Implementierung aufgrund des Overheads beim Aufruf der UDF langsamer als das Original sein.

Wenn Sie den führenden Platzhalter vermeiden können, würde eine computed column with an index wahrscheinlich die Leistung verbessern.

Ansonsten denke ich, Ihre einzige andere Option wäre Full-Text Search zu implementieren.

+0

Dies ist definitiv einfacher zu kapseln und verweisen auf die Funktion in der Abfrage, aber um klar zu sein, wird dies genauso langsam sein, aber wahrscheinlich langsamer als das Original. –

+0

@AaronBertrand Hmm ... Ich dachte, dass der größte Performance-Hit der vollständige Tabellen-Scan sein würde ... denkst du, dass das Umbrechen der 'replace'-Anweisungen in ein udf einen merklichen Overhead hinzufügen würde? –

+0

Nun, es gibt Overhead beim Aufruf der Funktion, und Sie werden die Funktion 2 x Zeilenanzahl während des Scans aufrufen (da es eine oder Bedingung gibt). Ich werde das in einer Antwort ansprechen, die ich entfernen werde. –

0

Dies ist keine Antwort auf die Frage, aber wird als Kommentar wirklich schwer zu implementieren sein.

Wenn Sie eine benutzerdefinierte Funktion verwenden, um die Abfrage selbst zu vereinfachen, tun Sie sich einen Gefallen und beschränken Sie die Funktionsaufrufe auf die Anzahl der Zeilen, die Sie haben, nicht doppelt.Statt:

where dbo.udf_StripQuotes(name) like 'dont%' 
    or dbo.udf_StripQuotes(name) like '% dont%'); 

tun:

where ' ' + dbo.udf_StripQuotes(name) like '% dont%'; 

Soweit das zugrunde liegende Problem, ich mit Michael darüber einig, dass eine indizierte berechneten Spalte am besten sein könnte, aber das wird nicht möglich sein, wenn der Name Spalte überschreitet 900 Bytes (und dies wird aufgrund der Platzhalter nicht magisch eine Suche zu einer Suche drehen, es entfernt nur die Notwendigkeit, eine Funktion aufzurufen oder alle diese Ersetzungsaufrufe in der Abfrage auszuführen).

+0

Volltextsuche in dieser Spalte kann eine Lösung sein? –

0

Effizient im Raum oder in der Zeit?

Ihre erste Lösung ist platzsparend, aber wahrscheinlich zeitaufwendig, da bei jeder Ausführung der Abfrage mehrere Zeichenfolgenfunktionen auf jede Zeile in der Tabelle angewendet werden.

Die Lösung einer generierten Spalte ist platzineffizient, aber wahrscheinlich zeiteffizient, da die Zeichenfolgenoperationen einmal angewendet werden (beim Hinzufügen der Spalte und dann beim Einfügen/Aktualisieren).

Aus der Sicht Ihrer Benutzer ist die Suche nach einer generierten Spalte wahrscheinlich die beste Lösung.

0

Versuchen Sie Folgendes, um alle Namen ohne Anführungszeichen oder Anführungszeichen zurückzugeben. Dadurch wird die Notwendigkeit der LIKE-Anweisungen vermeiden, die Notwendigkeit für eine andere Spalte zu vermeiden, und Ihre Abfrage beschleunigen:

SELECT Replace(
    Replace(
     Replace(
      Replace(
       Replace(
        Replace(Name, '“', ''), 
       '‘', ''), 
      '''',''), 
     '"', ''), 
    '’',''), 
'”', '') AS Name 
FROM tbl_MyTable 
Verwandte Themen