Laden...

[erledigt] Wie kann ich SQL Daten mit 95% Übereinstimmung finden? Per SQL oder im Programm?

Erstellt von ThomasE. vor 6 Jahren Letzter Beitrag vor 6 Jahren 3.383 Views
T
ThomasE. Themenstarter:in
461 Beiträge seit 2013
vor 6 Jahren
[erledigt] Wie kann ich SQL Daten mit 95% Übereinstimmung finden? Per SQL oder im Programm?

SQL Server 2012

Hallo,

wollte fragen ob es möglich ist, aus verschiedenen Tabellen/DB-Tabellen Daten zu finden, die z.Bsp. zu 95% zusammenpassen?

Ist dieses innerhalb eines SQL-select's möglich oder muß sowas in einem Programm gemacht werden?

Bitte um Info, vielen Dank!

Grüße,
Thomas

Ich habe den Titel mal angepasst, so dass Suchende auch etwas damit anfangen können. EDIT: Ich sollte beim Wort "Shift" im Titel das "f" nicht vergessen... 😄

P
1.090 Beiträge seit 2011
vor 6 Jahren

Was soll den zu 95% übereinstimmen?

Sollte man mal gelesen haben:

Clean Code Developer
Entwurfsmuster
Anti-Pattern

T
ThomasE. Themenstarter:in
461 Beiträge seit 2013
vor 6 Jahren

Hallo,

von Daten war die Rede, man selektiere aus einer Tabelle und aus einer Anderen, dann vergleiche man von je Tabelle eine Spalte miteinander, die dann zu 95% zusammenpassen sollten...

In meinem Fall würden lediglich nvarchar-Typen verglichen werden...

Grüße

Ich habe den Titel mal angepasst, so dass Suchende auch etwas damit anfangen können. EDIT: Ich sollte beim Wort "Shift" im Titel das "f" nicht vergessen... 😄

P
1.090 Beiträge seit 2011
vor 6 Jahren

Also (Beispeil vielleicht besser mit Wörtern und Sätzen vorstellen):

ab.length ist = ba.length weil beide die Gleiche länge haben.
ab = ba weil beide a und b enthalten.
und
ab = ab ist weil beides ab ist.

Wenn du mathematisch korrekt beschreiben kannst was 95% Übereinstimmung ist, sollte es kein Problem sein. Grundlegend gibt es für Texte verschiedene Algorithmen, die einen Grad an Übereinstimmung bestimmen können. Wo bei da aber durch aus unterschiedliche Sachen in Betracht gezogen werden.

Sollte man mal gelesen haben:

Clean Code Developer
Entwurfsmuster
Anti-Pattern

T
ThomasE. Themenstarter:in
461 Beiträge seit 2013
vor 6 Jahren

Hallo,

danke für deine Antwort.

Ja es stimmt, ist nicht einfach. Folgendes Beispiel könnte vorkommen, was wir vergleichen können müssen:

Tabelle1-Spalte1 = '12345-89 9'
Tabelle2-Spalte1 = '12345 89 9'

oder

Tabelle1-Spalte1 = '12345 89/9'
Tabelle2-Spalte1 = '12345-89 9'

oder

Tabelle1-Spalte1 = '1234589 9'
Tabelle2-Spalte1 = '12345 899'

...
...

Ich habe den Titel mal angepasst, so dass Suchende auch etwas damit anfangen können. EDIT: Ich sollte beim Wort "Shift" im Titel das "f" nicht vergessen... 😄

P
1.090 Beiträge seit 2011
vor 6 Jahren

Dass kannst du recht einfach mit RegEx vergleichen oder in dem du aus dem String alles entfernst was keine Zahl ist.

Sollte man mal gelesen haben:

Clean Code Developer
Entwurfsmuster
Anti-Pattern

T
ThomasE. Themenstarter:in
461 Beiträge seit 2013
vor 6 Jahren

Hey, aber du redest jetzt von einem Programm und nicht inerhalb eines SQL-Kommandos?

In einem Programm wüßte ich wie ich es angehen könnte.

REGEX in einem SQL? Kann das mit dem like-Operator umgesetzt werden?

Ich habe den Titel mal angepasst, so dass Suchende auch etwas damit anfangen können. EDIT: Ich sollte beim Wort "Shift" im Titel das "f" nicht vergessen... 😄

P
1.090 Beiträge seit 2011
vor 6 Jahren

Sollte man mal gelesen haben:

Clean Code Developer
Entwurfsmuster
Anti-Pattern

T
ThomasE. Themenstarter:in
461 Beiträge seit 2013
vor 6 Jahren

Danke!

Und ich muß mich entschuldigen, es können natürlich auch Buchstaben vorkommen, mein obiges Beispiel ward schnell eingetippt...

Was aber mit dem Link von dir dennoch umgesetzt werden kann.

Danke mal fürs Erste, die Lösung scheint durchaus praktikabel.

Ich habe den Titel mal angepasst, so dass Suchende auch etwas damit anfangen können. EDIT: Ich sollte beim Wort "Shift" im Titel das "f" nicht vergessen... 😄

R
69 Beiträge seit 2009
vor 6 Jahren

Hallo,

Levenshtein-Distanz.....

In der Praxis wird die Levenshtein-Distanz zur Bestimmung der Ähnlichkeit von Zeichenketten angewandt.

https://de.wikipedia.org/wiki/Levenshtein-Distanz

Muss dann mit einem Programm geprüft werden....

Gruß

Ron

286 Beiträge seit 2011
vor 6 Jahren

Das Problem mit der Levenshtein-Distanz ist nur, dass diese eigentlich erstaunlich wenig über das was wir Menschen als Ähnlichkeit zwischen Worten verstehen aussagt.

Mit der Distanz sind sich Worte zum Teil sehr nahe die wir Menschen völlig fernab sehen und umgekehrt, daher ist die für eine Suchfunktion eher ungeeignet, bzw nur als ein Mittel in einem größeren Algorithmus. Einfache nur _getLevenshteinDistance < 4 wird kaum brauchbare Ergebnisse liefern.

tl;dr; die Distanz kann sehr hilfreich sein, man muss aber für den Anwendungsfall genau prüfen, wie man sie einsetzt.
Edit als Ergänzung: Für eine SuFu ist die Distanz eigentlich ohnehin nicht gedacht. Und ich habe hier die DamerauLevenshtein-Distanz gepostet (welche eine Erweiterung der Levenshtein-Distanz ist)

Hier eine StringExtension für die Distanz:


    public static class DamerauLevenshtein
    {
        public static int DamerauLevenshteinDistanceTo(this string @string, string targetString)
        {
            return DamerauLevenshteinDistance(@string, targetString);
        }

        public static int DamerauLevenshteinDistance(string string1, string string2)
        {
            if (String.IsNullOrEmpty(string1))
            {
                if (!String.IsNullOrEmpty(string2))
                    return string2.Length;

                return 0;
            }

            if (String.IsNullOrEmpty(string2))
            {
                if (!String.IsNullOrEmpty(string1))
                    return string1.Length;

                return 0;
            }

            int length1 = string1.Length;
            int length2 = string2.Length;

            int[,] d = new int[length1 + 1, length2 + 1];

            int cost, del, ins, sub;

            for (int i = 0; i <= d.GetUpperBound(0); i++)
                d[i, 0] = i;

            for (int i = 0; i <= d.GetUpperBound(1); i++)
                d[0, i] = i;

            for (int i = 1; i <= d.GetUpperBound(0); i++)
            {
                for (int j = 1; j <= d.GetUpperBound(1); j++)
                {
                    if (string1[i - 1] == string2[j - 1])
                        cost = 0;
                    else
                        cost = 1;

                    del = d[i - 1, j] + 1;
                    ins = d[i, j - 1] + 1;
                    sub = d[i - 1, j - 1] + cost;

                    d[i, j] = Math.Min(del, Math.Min(ins, sub));

                    if (i > 1 && j > 1 && string1[i - 1] == string2[j - 2] && string1[i - 2] == string2[j - 1])
                        d[i, j] = Math.Min(d[i, j], d[i - 2, j - 2] + cost);
                }
            }

            return d[d.GetUpperBound(0), d.GetUpperBound(1)];
        }
    }

Tabelle1-Spalte1 = '12345-89 9'
Tabelle2-Spalte1 = '12345 89 9'
Tabelle1-Spalte1 = '12345 89/9'
Tabelle2-Spalte1 = '12345-89 9'
Tabelle1-Spalte1 = '1234589 9'
Tabelle2-Spalte1 = '12345 899'

Ich weiß nicht, ob das nur an dem erwähnten Beispiel liegt oder grundsätzlich ein Lösungsansatz für dich ist, aber sämtliche o.g. Ergebnisse würde man via


SELECT * FROM Tabelle1 WHERE Spalte1 LIKE '12345%'

erwischen.

2+2=5( (für extrem große Werte von 2)

5.658 Beiträge seit 2006
vor 6 Jahren

Hi ThomasE.,

du kannst auch mit SQL Zeichenketten suchen und ersetzen. Dann könntest du Leer- und Trennzeichen durch einen Leerstring ersetzen und nur die Ziffernfolgen vergleichen.

Besser wäre natürlich, die Werte gleich (zusätzlich) normalisiert in der DB zu speichern.

Weeks of programming can save you hours of planning

T
ThomasE. Themenstarter:in
461 Beiträge seit 2013
vor 6 Jahren

Hallo,

@ronny75, wir haben auch diese Lösung in Betracht gezogen, danke!

@emuuu, danke für deinen Code, wenn dann mal Zeit ist, werd ich mir das interesse halber sicher genauer ansehen. Das mit dem 'like'-Operator ist leider nicht möglich, ein REGEX wäre hier angebracher.

@MrSparkle, das wäre natürlich eine Alternative, nur hätte es ein wenig gedauert, bis wir alle möglichen ungültigen Zeichen herausgefunden hätten... Normalisiert in die DB zu speichern wäre natürlich ein Traum, nur leider spielts das nicht in dem Fall, wo auch manuelle Buchungen von Personen vollzogen werden können 8o (Fremdsystem)

Hatte es am Ende doch mit einem 1Stunden Programm umgesetzt, um die Vergleiche per REGEX durchzuführen. Dient nur für uns als Programmierer und ist somit nicht weiter schlimm.

Danke trotzdem für die vielen Lösungsvorschläge!

Ich habe den Titel mal angepasst, so dass Suchende auch etwas damit anfangen können. EDIT: Ich sollte beim Wort "Shift" im Titel das "f" nicht vergessen... 😄