Hallo liebe Community,
ich habe ein kleines/größeres Problem mit meiner Denkweise gerade und komm nicht drauf wie ich den unteren Code umschreiben könnte um ein SQL-Statement daraus zu erhalten.
Zur Aufgabe:
ich habe ein Suchfeld in welches ich max. 4 Suchparameter eingeben darf (können aber auch nur 2 oder 3 sein). Mit diesen Suchparametern will ich nun in der Datenbank (SQL) in 2 Spalten nach Ergebnissen suchen.
z.B:
Erster Parameter = a;
Zweiter Parameter = b;
mit diesen zwei Parametern gibt es also folgende Möglichkeiten
Besitzt Spalte 1 den Wert "a" oder Spalte 2 den Wert "b" oder
Besitzt Spalte 1 den Wert "b" oder Spalte 2 den Wert "a" oder
Besitzt Spalte 1 den Wert "a und b"
Besitzt Spalte 2 den Wert "a und b"
Mit 2 Parametern ist es relativ einfach, doch wenn wir nun von der maximalen Parameteranzahl ausgehen (4) ist dies schon ein wenig komplexer.
Zwar habe ich es iwie geschafft, meine testparameter abcd richtig zu sortieren, habe es leider jedoch nicht geschafft es so zu programmieren, dass ich nun aus dem Result gültige SQL-Syntaxen rausbekommen kann.
Nun meine Bitte an euch, wer kann mir auf die Sprünge helfen, wie ich den unteren kauderwelsch ordentlich und strukturiert programmieren könnte sodass ich auch meine AND und OR richtig hinter die Suchparameter hinbekomme?
Bin für jeden helfenden Ansatz dankbar 😃
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace ConsoleApp4
{
class Program
{
public static List<string> res2 = new List<string>();
static void Main(string[] args)
{
string suche = "a b c";
var inhalt = suche.Split(' ').ToList<string>();
//var values = Test2(inhalt);
var values = new List<string>();
var res = Test2(inhalt,new List<string>());
//Ausgabe
for (int i = 0; i < res.Count;i++)
{
Console.WriteLine(res[i] + "-->" + res2[i]);
// Console.WriteLine(res[i]);
}
Console.ReadKey();
}
private static List<string> Test2(List<string> inhalt, List<string> res)
{
string val = " ";
res.Add("");
//wir holen uns das erste Element
foreach (var elem in inhalt)
{
//wir haben nun unser erstes Element
res.Add(elem);
val = elem;
//wir benötigen ein Flag für alle Elemente auf einer Seite
bool containsAll = false;
//wir müssen uns für die zweistelligen eine Merkvariable machen
var valLengthZwei = val;
//wir durchlaufen nun Element für Element
for (int i = 0; i < inhalt.Count(); i++)
{
if (inhalt[i] != elem)
{
//wir bauen alle zweier Kombinationen
if (!(res.Contains(String.Join(valLengthZwei, inhalt[i])) || res.Contains(String.Join(valLengthZwei, inhalt[i]).Reverse())))
{
val += String.Join(val, inhalt[i]);
res.Add(String.Join("", valLengthZwei, inhalt[i]));
}
//wir holen uns alle Anderen
if (val.Length != 2 && !(res.Contains(val)))
{
res.Add(val);
}
var Val3Stellig = val;
//Wenn wir bei val.Length bei 3 Stellen sind müssen wir nochmal durchlaufen jedoch den zweiten wert um 1 inkrementiert
if(val.Length == 2)
{
for (int a = inhalt.Count; a==1; a--)
{
Val3Stellig += String.Join(val, inhalt[a]);
Console.WriteLine(Val3Stellig);
if(!(res.Contains(Val3Stellig)))
{
res.Add(Val3Stellig);
}
}
}
}
}
}
//durchlaufe nun jedes Element und Buchstaben von jedem Element und prüfe welcher fehlt
foreach (var elem in res)
{
val = "";
for (int i = 0; i < inhalt.Count; i++)
{
if (elem.Contains(inhalt[i]))
{
continue;
}
else
{
val += inhalt[i];
}
}
res2.Add(val);
}
//Wir machen die Gegenprüfung
foreach (var elem2 in res2.ToList())
{
if (!(res.Contains(elem2)))
{
res.Add(elem2);
val = "";
for (int i = 0; i < inhalt.Count; i++)
{
if (elem2.Contains(inhalt[i]))
{
continue;
}
else
{
val += inhalt[i];
}
}
res2.Add(val);
}
}
return res;
}
}
}
LG Sam
PS: Tut mir leid für diesen grauenvollen Code, bin jedoch froh, dass ich die Parameter iwie sortiert bekommen hab ^^
Liebe Grüße
Sam
select ... from Table1 where col1 in (a,b) or col2 in (a,b)
**:::
@vbprogger
Danke für die Antwort, doch dies wird nicht funktionieren, denn er soll ja aus einem String die
SQL-Statements automatisch mit allen Kombinationen (wie in meinem Bild zu sehen) erstellen.
Dies wären bei 4 Suchparametern = 16 Statements
bei 3 Parametern = 8 Statements
und bei 2 Parametern = 4 Statements
Also das richtige zusammenbauen (leider total verkopft und sicherlich alles andere als Performant) habe ich geschafft, doch nun kann ich mein AND und OR nicht mehr setzten, da es einfach alles zu planlos meinerseits programmiert wurde.
Ich muß zugeben, dass ich mit meinem Latein bzgl. dieser Aufgabe am Ende bin. Ich müsste jetzt quasi nur noch das AND hinter jeden Parameter klemmen, doch dazu hätte ich wohl einen anderen Weg wählen sollen, der mir jedoch fehlt.
Ich habe es mit einer Rekrusion versucht, doch damit habe ich mich noch mehr verrannt 😦.
Wie würde denn dein Code/Pseudocode aussehen, wenn du a ; b ; c ; d in 2 Spalten aufteilen willst? Ich denke das ist hier das Hauptproblem, denn mein Code ist um ehrlich zu sein einfach dumm :'(. Allerdings zeigt er, dass ich mir viele Gedanken gemacht habe und keine fertige Lösung will, weil ich zu faul bin 😃.
Liebe Grüße
Sam
Du willst bei den X Parametern, daß auch alle in eine der beiden Spalten vorhanden sind (AND)?
Und bei
Besitzt Spalte 1 den Wert "a und b" meinst du "Enthält Spalte 1 den Wert a und b"?
Wenn es sich bei beiden Spalten um Strings handelt, dann verbinde diese zuerst und suche dann dadrin:
SELECT ... FROM table WHERE CONCAT(col1, col2) LIKE '%a%' AND CONCAT(col1, col2) LIKE '%b%' AND ...
Kannst du z.B. unter SQL Server CONCAT() folgendermaßen ausprobieren
SELECT * FROM Customers WHERE CONCAT(CustomerName, ContactName) LIKE '%an%' AND CONCAT(CustomerName, ContactName) LIKE '%tr%'
So kannst du den SQL-String einfach linear erstellen (d.h. je Parameter eine AND-LIKE Bedingung).
Wasfür Daten hast du in den Spalten 1 und 2? Stringwerte? Und du suchst nach Vorkommen von Buchstaben a und/oder b? Oder a und sind Variablennamen? Ich kann dir ehrlich gesagt nicht folgen.
**:::
a ; b ; c ; d sollen nur die Suchparameter darstellen (also Variablen).
Beispiel: Folgende Suchparameter habe ich :
ane ; ber ; ank ; rch
Anhand dieser Parameter will ich in der Tabelle Schüler z.B. Vor- u. Nachname suchen
Select * from Tabelle
Where Vorname like '%ane%' AND Vorname like '%ber%' AND Vorname like '%and%' AND Vorname like '%rch%'
OR
Vorname like '%ane%' AND Vorname like '%ber%' AND Vorname like '%ank%' AND Nachname like '%rch%'
OR
Vorname like '%ane%' AND Vorname like '%ber%' AND Nachname like '%ank%' AND Nachname like '%rch%'
und so weiter, bis jede Konstellation aller Parameter durchgelaufen sind. Wichtig ist, dass keiner der Suchparameter auf beiden Seiten vorkommen darf.
Hier noch ein Screen vlt verdeutlicht er mein Problem besser
Liebe Grüße
Sam
@samkirchner
Du solltest deine Like Abfragen in Klammern packen, sonst führst du die WHERE Bedingung durch OR/AND Kombinationen ins chaotische.
Also so:
Select * from Tabelle
Where (Vorname like '%ane%' AND Vorname like '%ber%' AND Vorname like '%and%' AND Vorname like '%rch%' )
OR
(Vorname like '%ane%' AND Vorname like '%ber%' AND Vorname like '%ank%' AND Nachname like '%rch%' )
OR
(Vorname like '%ane%' AND Vorname like '%ber%' AND Nachname like '%ank%' AND Nachname like '%rch%')
Somit wird deine Logik, eben anch unterschiedlichen Mustern in Vorname und Nachname, auch sauber umgesetzt.
Ebenfalls sollten deine fertigen Abfragen dann auch SQL Parameter verwenden.
Die Abfrage selbst kann aber abhängig von der Größe der Tabelle und der Kombination deiner WHERE Abfragen sehr unperformant werden.
Du stellst die DB mit der Abfrage schon vor eine kleine Herrausforderung, da du nicht z.B. Vorname/Nachname als Kombination prüfst sondern auch mal Vorname/Vorname oder Nachname/Nachname.
Dies ist für die Datenbank sehr schlecht um z.B. per Index über Vorname/Nachname die Daten zu suchen.
Im schlimmsten Fall muss für die Abfrage die gesamte Tabelle gelesen werden, was nach Menge der Daten viel Zeit und Leistung kosten kann.
T-Virus
Developer, Developer, Developer, Developer....
99 little bugs in the code, 99 little bugs. Take one down, patch it around, 117 little bugs in the code.
Hallo samkirchner,
hattest du meinen Beitrag gelesen? Oder was gefällt dir daran nicht?
Edit: Und wenn du das CONCAT (bzw. du kannst auch '+' benutzen) nur einmal schreiben willst, dann so
SELECT * FROM (SELECT *, CONCAT(CustomerName, '#', ContactName) AS X FROM Customers) T WHERE X LIKE '%an%' AND X LIKE '%tr%' AND X LIKE '%er%'
(ich habe außerdem noch ein Trennzeichen eingefügt)
@Th69
doch ich hatte deinen Beitrag gelesen, jedoch bin ich davon ausgegangen, dass nicht klar war was ich meine 😃.
Problem a ist nach wie vor, eine strukturierte Form eine Liste zu erstellen, welche eben wie bereits in den anderen Beiträgen meinerseits beschrieben die Aufteilung von max. 4 Variablen erstellt.
Wie bereits gesagt, ich habe es geschafft alles richtig zu sortieren
a --> bcd
ab --> cd
abc --> d
etc. etc.
Ich suche derzeit einfach nach einer strukturierte Lösung das anders zu machen um danach meine SQL bauen zu können. Leider bin ich diesbezüglich noch immer nicht weiter, zumal ich letzte Woche auch noch flach lag 😦.
Aus diesem Grund dachte ich, dass mir dein Concat nichts nützt bis ich die oben erwähnte Struktur besser hinbekomme.
@T-Virus
Die SQL-Parameter werden noch gemacht, doch das ist nach meinem eigentlichen Problem 😃.
Zur Thematik der Performance kann ich nur sagen, dass du wohl recht haben wirst, doch leider wird dies so gefordert 😦.
Liebe Grüße
Sam
Sorry, aber ich verstehe (immer noch) nicht wofür du die Sortierung überhaupt brauchst?
Wahrscheinlich soll das so eine Art Volltext-Suche mit Gewichtung werden. Da gibt es allerdings fertige Lösungen für die meisten DB-Systeme.
Weeks of programming can save you hours of planning
Sorry, aber ich verstehe (immer noch) nicht wofür du die Sortierung überhaupt brauchst?
Um ganz ehrlich zu sein ich auch nicht ^^. Doch warum diese Aufgabe so ist, spielt für mich keine Rolle.
Nun ja, dann werde ich die Suchparameter doch in ein dict o. Array packen und nicht die Suchbegriffe aufteilen sondern die indexe
quasi statt dem oberen "a" "b" "c" "d" durch 1,2,3,4 ersetzten. Hätte mir zwar eine schönere Lösung erhofft, aber muss dann halt nu so gehen.
danke für die Antworten.
Liebe Grüße
Sam