![]() |
Datenbank: firebird • Zugriff über: ibx, ibexpert
sql für ganz harte
hallo
ich hab ein problem und weiß wieder mal nicht, wie ich es in sql ausdrúcken kann: man stelle sich vor: tabelle t1, folgendermaßen: t1.f1: integer (fremdschlüssel auf andere tabelle) t1.f2: integer (fremdschlüssel auf id von tabelle t2) tabelle t2, folgendermaßen: t2.id: integer t2.wert: string; bevor ich meine suchbedingung darlege, noch paar definition, sonst erklärt sich das schlecht: IstGleich(t1,t2)..gibt mir eine liste von datensätzen zurück, dabei: -ist jeder datensatz eine teilmenge von t2 -sind zwei oder mehr records in einem datensatz (Menge X) enthalten, dann heißt das, dass diejenigen einträge (Menge Y) aus t1, deren f2 auf die einträge von x verweisen, alle den gleichen wert f1 haben Summe(L)..nimmt eine Liste L von Datensätzen entgegen und gibt mir eine Liste von Strings wieder -der String[i] der ergebnisliste ist das ergebnis der des records r[i] der ausgansgsliste -die Summe eines datensatzes ist die konkatenation des feldes 'wert' aller datensätze in dem datensatz sortiert nach dem feld 'id' so, jetz brauch ich einen sql-query der über einen string s nach folgendem sucht: alle werte für t1.f1, für die gilt: Summe(IstGleich(t1,t2)) is like s ich hab's versucht so akkurat wie möglich auszudrücken; hoffentlich versteht ihr was ich meine... danke martin |
Re: sql für ganz harte
Werde mal etwas konkreter, sonst wird das nicht. -> Beispiel
|
Re: sql für ganz harte
Also ich hab mir das nun 5 mal durchgelesen und ich hab 0 verstanden...
Du solltest ein paar beispiel Daten posten, was nach den Funktionen rauskommt, was Genau X, Y und L ist schreiben und wo genau dein Problem ist und was du genau für das Beispiel für ein Ergebniss erwartest :wink: Eventuell schon Code den du schon hast :stupid: Bye |
Re: sql für ganz harte
ok, angenommen, ich habe in meiner tabelle t1 folgende einträge (ich hatte im vorherigen post vergessen zu erwähnen, dass t1 auch noch ein feld 'id' hat)
f1 = 1, f2 = 2, id = 2 f1 = 1, f2 = 1, id = 1 f1 = 1, f2 = 3, id = 3 f1 = 2, f2 = 2, id = 5 f1 = 2, f2 = 1, id = 4 f1 = 3, f2 = 2, id = 6 f1 = 3, f2 = 3, id = 7 jetzt ein paar beispieleinträge für t2: id = 1, wert = 'wie ' id = 2, wert = 'geht ' id = 3, wert = 'das?' jetzt sei mein suchstring s = 'wie geht %' als ergebnismenge müsste ich 2 datensätze bekommen, der erste hat das feld f1 = 1, der zweite hat f1 = 2... warum? schaut man sich die ersten drei einträge an, dann sieht man, dass sie zusammengehören, da sie den gleichen wert für f1 haben. daher lässt sich ein "kombinierter string" bilden (ich nenn das jetz mal so), und dieser kombinierte string ist 'wie geht das?' (die datensätze aus t1 müssen bei bildung dieses strings nach t1.id sortiert sein)...und 'wie geht das?' is like 'wie geht %' daher kommt das entsprechende f1 in die ergebnismenge dito für den vierten und fünften eintrag: sie haben beide den gleichen wert f1; ihr kombinierter string ist 'wie geht ' auch 'wie geht ' is like 'wie geht %' -> auch ihr wert für f1 (2) kommt in die ergebnismenge beim sechsten und siebten eintrag (sie gehören zusammen, weil gleiche f1-werte) ist der kombinierte string aber 'geht das? 'geht das' is not like 'wie geht %' .. daher kommt 3 NICHT in die ergebnismenge... isses jetz ein bisschen klarer was ich meine? danke und gruß, martin |
Re: sql für ganz harte
Zitat:
|
Re: sql für ganz harte
Hi,
es könnte evtl. über eine SP funktionieren, aber nur weil man es machen kann, sollte man es nicht unbedingt machen. Letztenendes ist das nämlich eine sequentielle Suche innerhalb der DB (alle Datensätze müssen angefasst werden). Selbst wenn Du das in eine SP auslagerst, kostet das (eine gewisse Größe der DB vorausgesetzt) zu viel Zeit und Ressourcen. Kannst Du das Design der DB nicht umgestalten? Was willst Du eigentlich erreichen? Lemmy |
Re: sql für ganz harte
Ah.... ich verstehe.
SQL-Code:
Das liefert Dir eine Tabelle aller F1 mit den entsprechenden Werten.
Create View Words
as select t1.f1, t2.wert from t1 join t2 on t1.f2 = t2.ID Nun willst Du die F1, die die Wörter 'wie' und 'gehts' enthalten:
SQL-Code:
So oder ähnlich müsste es funktionieren. Damit das allgemeingültig wird, müsstest Du die zweite Anweisung dynamisch erzeugen:
Select distinct w1.f1
from Words w1 join words w2 on w1.f1 = w2.f1 where w1.wert = 'wie' and w2.wert = 'gehts' Suche nach einem Wort:
SQL-Code:
Suche nach zwei Wörtern:
Select distinct w1.f1
from Words w1 where w1.Wert = 'wie'
SQL-Code:
Nach drei Wörtern:
Select distinct w1.f1
from Words w1 join words w2 on w1.f1 = w2.f1 where w1.wert = 'wie' and w2.wert = 'gehts'
SQL-Code:
Bestimmt geht das auch ohne die View und noch kürzer.
Select distinct w1.f1
from Words w1 join words w2 on w1.f1 = w2.f1 join words w3 on w1.f1 = w3.f1 where w1.wert = 'wie' and w2.wert = 'gehts' and w3.wert = 'Foo' |
Re: sql für ganz harte
ihr habt mich leider noch nicht ganz verstanden:
der suchstring über den ich beispielsweise suche ist s = 'wie geht %' nochmal meine einträge aus t1: f1 = 1, f2 = 2, id = 2 f1 = 1, f2 = 1, id = 1 f1 = 1, f2 = 3, id = 3 f1 = 2, f2 = 2, id = 5 f1 = 2, f2 = 1, id = 4 f1 = 3, f2 = 2, id = 6 f1 = 3, f2 = 3, id = 7 und aus t2: id = 1, wert = 'wie ' id = 2, wert = 'geht ' id = 3, wert = 'das?' zuerst müsste t1 in teilmengen zerlegt werden, wobei für JEDE teilmenge T gilt, dass die einträge in T ALLE den gleichen wert f1 haben => in diesem beispiel müsste es 3 teilmengen geben; T1: eintrag 1-3, T2: eintrag 4-5, T3: eintrag 6-7..soweit klar, oder? für jede teilmenge T müsste jetzt der sogenannte "kombinierte string" gebildet werden. dieser bildet sich wie folgt: schritt 1: man sortiere die einträge aus T nach dem feld id schritt 2: jetzt suche man zu jedem eintrag x aus T das entsprechende gegenstück y aus tabelle t2 und zwar über den fremdschlüssel t1.f2; die gesamtheit aller y sei T'; die einträge in T' werden NICHT neu sortiert, sondern sie BLEIBEN sortiert nach t1.id (siehe schritt 1) schritt 3: man konkateniere die felder 'wert' aller einträge aus T' =>der "kombinierte string" von T1 wäre 'wie geht das?', der von T2 'wie geht ' und der von T3 'geht das?' =>für T1 und T2 trifft die suchbedingung also zu, da -'wie geht das?' is like 'wie geht %' und -'wie geht ' is like 'wie geht' DESWEGEN soll mir also der sql-query, den ich suche also die vereinigung von t1.f1 = 1 und t1.f1 = 2 zurückgeben jetzt verstanden? danke, martin Zitat:
Zitat:
|
Re: sql für ganz harte
Das ist mir schon klar, aber vielleicht änderst du einfach deinen Suchstring, bzw. bastelst Dir eine kleine Funktion, die das macht. Meine Lösung dürfte jedenfalls funktionieren, wenn man die Frage (also den Suchstring) anders formuliert, nämlich: Ich suche alle F1, die mindestens "die in dieser Liste enthaltenen Wörter" enthalten:
Delphi-Quellcode:
Diese Routine dürfte ungefähr die Abfrage so formulieren, wie ich es vorgeschlagen habe. Deine Aufgabe ist es nun, deinen Suchtext ('Wort1 Wort2 %') in eine Stringliste zu verwandeln. Wenn das '%' bedeutet soll, das die gesuchten F1 MINDESTENS diese Wörter enthalten muss, dann kannst musst Du noch den Fall behandeln, wenn man das '%' weglässt. Dann muss die Wortmenge je F1-Wert GENAU mit der Wortliste übereinstimmen.
Function CreateSQL (aWords : TStringList) : String;
Var sJoin,sWhere : String; Begin sJoin := 'Words w1'; sWhere := Format('w%d.wert = %s',[1,QuotedStr(aWords[0]]); For i:=1 to aWords.count - 1 do begin sJoin := sjoin + Format (' join words w%d on w%d = w%0:d.f1',[i,i-1]); sWhere := sWhere + Format('and w%d.wert = %s',[i+1,QuotedStr(aWords[i]]); End; Result := Format ('Select distinct w1.f1 from %s where %s',[sJoin, sWhere]); End; Wenn die Reihenfolge der Wörter auch noch eine Rolle spielt, dann musst Du die Where-Klausel je Wort noch erweitern. [edit] Nach mehrmaligem Durchlesen Deiner Anwort verstehe ich deine Kritik... Dir ist es lieber, die Wortliste je F1 in diesen String zu konkatenieren und DANN zu suchen, dann kann man den LIKE-Operator natürlich besser verwenden... DAS scheint nur mit einer stored Procedure zu gehen. Für den Fall, das du nur Übereinstimmungen einzelner Wörter suchst, ist meine Methode jedoch ausreichend. Ach ja: Eine gute DB sollte niemals lange für eine Suche benötigen (Aggregate sind eine andere Sache) [/edit] |
Re: sql für ganz harte
der suchstring kann aber vor der suche nicht zerlegt werden, weil du ja gar nicht weißt wie du ihn zerlegst
'wie geht %' kann zerlegt werden in: 'w' + 'ie geht %' oder 'wie g' + 'eht %' oder 'w' + 'ie geht %' usw... |
Re: sql für ganz harte
Na ja. Ich ging davon aus, das eine Art Volltextsuche auf Wortbasis implementiert werden soll. Deine Beispiele sahen ja wirklich so aus.
Einen praktischen Einsatz einer Suche nach '%ie geh%' kann ich mir zwar nicht vorstellen, aber wenn Du diese Funktionalität unbedingt zur Verfügung stellen willst, dann geht es nicht anders, als mit einem Prozeduralen Ansatz. Aber dann verstehe ich die Tabellenstruktur auch nicht. Das erinnert mich nämlich an eine Wortliste, um z.B. Zeitschriftenartikel zu indizieren. Es wird dir nichts anders übrig bleiben, als die Wörter der einzelnen F1-Gruppen jeweils zu konkatenieren und dann per 'LIKE' zu suchen. Wie groß ist denn die Tabelle ungefähr? Bei <10000 Records dürfte das noch vertretbar sein. Man muss bei Features dieser Art aber bedenken, das der DB-Server u.U. ganz schön beschäftigt ist und in der Zeit normale Anfragen viel länger dauern... |
Re: sql für ganz harte
halb so wild..hab mittlerweile ne ausweichlösung
wär wohl wirklich zu rechenintensiv geworden, ich weiß... die anwendung ist ein terminologieverwaltungssystem, aber wie gesagt, da müsst ich jetz nen aufsatz schreiben..warum, weshalb, wieso.. gruß, martin |
Alle Zeitangaben in WEZ +1. Es ist jetzt 19:06 Uhr. |
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz