7

Ich suche ein Muster für die Durchführung einer dynamischen Suche auf mehreren Tabellen.Need-Muster für die dynamische Suche von mehreren SQL-Tabellen

Ich habe keine Kontrolle über die Legacy (und schlecht entworfen) Datenbanktabelle Struktur.

Stellen Sie sich ein Szenario ähnlich einer Wiederaufnahme-Suche vor, bei dem ein Benutzer eine Suche nach den Daten im Lebenslauf durchführen und eine Liste der Lebensläufe abrufen möchte, die ihren Suchkriterien entsprechen. Jedes Feld kann jederzeit und in Kombination mit einem oder mehreren anderen Feldern durchsucht werden.

Die tatsächliche SQL-Abfrage wird dynamisch erstellt, abhängig davon, welche Felder durchsucht werden. Die meisten Lösungen, die ich gefunden habe, beinhalten komplizierte if Blöcke, aber ich kann nicht anders, als zu denken, dass es eine elegantere Lösung geben muss, da dies ein gelöstes Problem sein muss.


Ja, also habe ich den Weg der dynamischen Erstellung der SQL in Code begonnen. Scheint gottesfürchtig zu sein. Wenn ich wirklich versuche, die angeforderte Fähigkeit zu unterstützen, irgendeine Kombination irgendeines Feldes in irgendeiner Tabelle abzufragen, wird dies ein MASSIVER Satz von if-Anweisungen sein. Schauer


Ich glaube, ich lese, dass COALESCE funktioniert nur, wenn Ihre Daten NULLs nicht enthalten. Ist das korrekt? Wenn ja, nein, da ich überall NULL-Werte habe.

Antwort

5

Soweit ich verstehe (und ich bin auch jemand, der gegen eine schreckliche Legacy-Datenbank geschrieben hat), gibt es keine dynamischen WHERE-Klauseln. Es wurde NICHT gelöst.

Persönlich bevorzuge ich meine dynamische Suche in Code zu generieren. Erleichtert das Testen. Beachten Sie, wenn Sie Ihre SQL-Abfragen im Code erstellen, nicht in Benutzereingaben verketten. Verwenden Sie Ihre @ Variablen!

Die einzige Alternative ist die Verwendung des COALESCE-Operators. Nehmen wir an, Sie haben die folgende Tabelle:

und Sie möchten optional nach Namen oder Spitznamen suchen. Die folgende Abfrage wird dies tun:

SELECT Name, Nickname 
FROM Users 
WHERE 
    Name = COALESCE(@name, Name) AND 
    Nickname = COALESCE(@nick, Nickname) 

Wenn Sie etwas nicht suchen wollen, nur in einem null übergeben. Zum Beispiel, vorbei in „brian“ für @name und null für @ Nick Ergebnisse in der folgenden Abfrage ausgewertet:

SELECT Name, Nickname 
FROM Users 
WHERE 
    Name = 'brian' AND 
    Nickname = Nickname 

Der coalesce Bediener dreht die Null in eine Identitäts Bewertung, die immer wahr ist und was nicht beeinflussen die Where-Klausel.

1

Suche und Normalisierung können im Widerspruch zueinander stehen. Also wahrscheinlich wäre die erste Sache, eine Art "Ansicht" zu bekommen, die alle Felder zeigt, die als eine einzelne Reihe mit einem einzelnen Schlüssel gesucht werden können, der Ihnen den Lebenslauf holt. dann können Sie etwas wie Lucene davor werfen, um Ihnen einen Volltextindex dieser Zeilen zu geben, die Art, wie das funktioniert, Sie fragen es nach "x" in dieser Ansicht und es gibt Ihnen den Schlüssel zurück. Es ist eine großartige Lösung und wird von Joel selbst auf dem Podcast innerhalb der ersten 2 Monate IIRC empfohlen.

1

Was Sie brauchen, ist etwas wie SphinxSearch (für MySQL) oder Apache Lucene.

Wie Sie in Ihrem Beispiel das läßt einen Lebenslauf vorstellen, die aus mehreren Feldern zusammengesetzt werden:

  • Liste item
  • Namen
  • Adreess,
  • Bildung (dies könnte eine Tabelle sein eine eigene) oder
  • Berufserfahrung (dies könnte zu einer eigenen Tabelle wachsen, wo jede Zeile einen früheren Job darstellt)

Die Suche nach einem Wort in allen Feldern mit WHERE wird schnell zu einer sehr langen Abfrage mit mehreren JOINS.

Stattdessen können Sie Ihren Referenzrahmen ändern und denken Sie an den gesamten Lebenslauf als was ist ein einzelnes Dokument, und Sie wollen nur dieses Dokument suchen.

Dies ist, wo Werkzeuge wie Sphinx Search tun. Sie erstellen einen FULL TEXT-Index für Ihr 'Dokument' und Sie können dann sphinx abfragen, und es wird Ihnen zurückgeben, wo in der Datenbank dieser Datensatz gefunden wurde.

Wirklich gute Suchergebnisse.

Machen Sie sich keine Sorgen darüber, dass diese Tools nicht Teil Ihres RDBMS sind, es wird Ihnen viele Kopfschmerzen ersparen, das entsprechende Modell "Documents" im Gegensatz zu dem falschen "TABLES" für diese Anwendung zu verwenden.