Laden...

Suchbegriffe für SQL-Statement zusammenstellen (Logik zur Aufteilung)

Erstellt von samkirchner vor 5 Jahren Letzter Beitrag vor 5 Jahren 2.147 Views
S
samkirchner Themenstarter:in
15 Beiträge seit 2016
vor 5 Jahren
Suchbegriffe für SQL-Statement zusammenstellen (Logik zur Aufteilung)

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

1.696 Beiträge seit 2006
vor 5 Jahren

select ... from Table1 where col1 in (a,b) or col2 in (a,b)

Ich bin verantwortlich für das, was ich sage, nicht für das, was du verstehst.

**:::

S
samkirchner Themenstarter:in
15 Beiträge seit 2016
vor 5 Jahren

@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

4.939 Beiträge seit 2008
vor 5 Jahren

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).

1.696 Beiträge seit 2006
vor 5 Jahren

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.

Ich bin verantwortlich für das, was ich sage, nicht für das, was du verstehst.

**:::

S
samkirchner Themenstarter:in
15 Beiträge seit 2016
vor 5 Jahren

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

T
2.223 Beiträge seit 2008
vor 5 Jahren

@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.

4.939 Beiträge seit 2008
vor 5 Jahren

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)

S
samkirchner Themenstarter:in
15 Beiträge seit 2016
vor 5 Jahren

@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

4.939 Beiträge seit 2008
vor 5 Jahren

Sorry, aber ich verstehe (immer noch) nicht wofür du die Sortierung überhaupt brauchst?

5.658 Beiträge seit 2006
vor 5 Jahren

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

S
samkirchner Themenstarter:in
15 Beiträge seit 2016
vor 5 Jahren

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