Discussion:
mysql Query JOIN mit LIKE (2 Spalten vergleichen)
(zu alt für eine Antwort)
Ben Butschko
2009-03-10 08:20:42 UTC
Permalink
Moin aus Kiel,

ich habe da ein kleines Problem:

Ich möchte mögliche Doubletten aus zwei Tabellen ermitteln.
Dazu verwende ich JOIN.

Nun kann es aber sein, dass der Firmenname von einem Benutzer X nicht
100% korrekt in die Datenbank gespeichert wurde - sprich ich müsste ein
LIKE verwenden.

Diese Query wird aber NICHT mit variablen Sucheingaben aus einem
Formular befüllt!

Hier mal mein Query:

SELECT DISTINCT crm.id AS crm_id, crm.company AS crm_company

FROM potential_clients crm

JOIN customer_table ag ON ( crm.company = ag.company)

GROUP BY crm.company HAVING COUNT(*) >= 1

Und hier liegt der "Hund" begraben -> JOIN ... ON ( crm.company =
ag.company)!

Ich müsste an dieser Stelle sowas wie ein crm.company LIKE
'%ag.company%' haben. Aber wie genau muss ich dies schreiben?

Für Anregungen und Tipps bedanke ich mich schonmal :0)

Gruß
Ben
Claus Reibenstein
2009-03-10 09:00:50 UTC
Permalink
Post by Ben Butschko
SELECT DISTINCT crm.id AS crm_id, crm.company AS crm_company
¯¯¯¯¯¯¯¯¯ ¯¯¯¯¯¯¯¯¯¯¯¯¯¯

Welchen Sinn und Zweck haben diese Aliase? Sie werden nirgends benutzt,
und kürzer sind sie auch nicht.
Post by Ben Butschko
Und hier liegt der "Hund" begraben -> JOIN ... ON ( crm.company =
ag.company)!
Ich müsste an dieser Stelle sowas wie ein crm.company LIKE
'%ag.company%' haben. Aber wie genau muss ich dies schreiben?
crm.company LIKE CONCAT('%', ag.company, '%')

Gruß. Claus
Ben Butschko
2009-03-10 09:43:29 UTC
Permalink
Post by Claus Reibenstein
Post by Ben Butschko
SELECT DISTINCT crm.id AS crm_id, crm.company AS crm_company
¯¯¯¯¯¯¯¯¯ ¯¯¯¯¯¯¯¯¯¯¯¯¯¯
Welchen Sinn und Zweck haben diese Aliase? Sie werden nirgends benutzt,
und kürzer sind sie auch nicht.
Der vollständigkeit halber hier das komplette Query:

// --

SELECT DISTINCT

id AS crm_id, company AS crm_company

FROM pb_potential_clients

GROUP BY company HAVING COUNT(*) > 1

UNION

SELECT DISTINCT

crm.id AS crm_id, crm.company AS crm_company

FROM potential_clients crm

JOIN customer_table ag ON ( crm.company LIKE CONCAT('%', ag.company, '%'))

GROUP BY company HAVING COUNT(*) >= 1

UNION

SELECT DISTINCT

crm.id AS crm_id, crm.company AS crm_company

FROM potential_clients crm

JOIN customer_archive_table ag_archive ON ( crm.company LIKE CONCAT('%',
ag_archive.company, '%'))

GROUP BY company HAVING COUNT(*) >= 1

ORDER BY crm_id DESC

// --

Wie man sieht, will ich einen Doublettenabgleich in drei Tabellen machen:

Potentielle Neukunden (potential_clients)
Live-Datenbestand (customer_table)
Archiv-Datenbestand (customer_archive_table)
Post by Claus Reibenstein
crm.company LIKE CONCAT('%', ag.company, '%')
Dieser Ansatz ist soweit schonmal gut, jedoch habe ich mit LIKE ein
massives Performance-Problem (und es liegt nicht am DB-Server: 24 GB
RAM, 4x Quadcore)

Die LIKE Abfragen, egal ob mit CONCAT oder nicht, dauern ~ 15 Sekunden.
Meiner Meinung nach zu lange.

Gruß
Ben
Ben Butschko
2009-03-10 09:06:38 UTC
Permalink
Ben Butschko schrieb:
....
Post by Ben Butschko
SELECT DISTINCT crm.id AS crm_id, crm.company AS crm_company
FROM potential_clients crm
JOIN customer_table ag ON ( crm.company = ag.company)
GROUP BY crm.company HAVING COUNT(*) >= 1
...

Ich habe einfach mal ein JOIN customer_table ag ON (crm.company LIKE
ag.company) gemacht.

Natürlich sind dort auch nicht die erwünschten Treffer vorhanden.
Aber ein großer Nachteil fällt mir jetzt schon auf:

Die Ausführungszeit:

Bei einem = liegt diese bei ca. 0.203 Sek. (laut DBVisualizer) und bei
einem einfachen LIKE schon bei 13.924 Sek.

Beide Tabellen haben natürlich Indizes gesetzt und beide Tabellen haben
relativ wenig Daten (crm = 3000 Datensätze, ag = 5000 Datensätze).

Wenn jemand hier eine performantere Lösung kennt, das wäre klasse :o)

Danke
Andreas Kretschmer
2009-03-10 09:10:56 UTC
Permalink
Post by Ben Butschko
FROM potential_clients crm
JOIN customer_table ag ON ( crm.company = ag.company)
GROUP BY crm.company HAVING COUNT(*) >= 1
Und hier liegt der "Hund" begraben -> JOIN ... ON ( crm.company =
ag.company)!
Ich müsste an dieser Stelle sowas wie ein crm.company LIKE
'%ag.company%' haben. Aber wie genau muss ich dies schreiben?
Für Anregungen und Tipps bedanke ich mich schonmal :0)
Was hast Du denn versucht?

Hier¹ funktioniert folgendes:


test=*# select * from namen;
id | name
----+-----------------------------
1 | batzenlurch
3 | ads
2 | kleine Tamara, meine tochter
(3 rows)

test=*# select * from foo;
id | name
----+-------------
1 | batzenlurch
3 | ads
2 | Tamara
(3 rows)

test=*# select foo.*, namen.* from foo left join namen on (namen.name ~ foo.name ) ;
id | name | id | name
----+-------------+----+-----------------------------
1 | batzenlurch | 1 | batzenlurch
3 | ads | 3 | ads
2 | Tamara | 2 | kleine Tamara, meine tochter
(3 rows)


¹ damit ist aber PostgreSQL gemeint. Ob und wie das in MySQL geht, ist
mir nicht bekannt.



Andreas
--
Andreas Kretschmer
Linux - weil ich es mir wert bin!
GnuPG-ID 0x3FFF606C http://wwwkeys.de.pgp.net
Christian Kirsch
2009-03-10 09:35:16 UTC
Permalink
Post by Ben Butschko
Moin aus Kiel,
Ich möchte mögliche Doubletten aus zwei Tabellen ermitteln.
Dazu verwende ich JOIN.
Nun kann es aber sein, dass der Firmenname von einem Benutzer X nicht
100% korrekt in die Datenbank gespeichert wurde - sprich ich müsste ein
LIKE verwenden.
Diese Query wird aber NICHT mit variablen Sucheingaben aus einem
Formular befüllt!
SELECT DISTINCT crm.id AS crm_id, crm.company AS crm_company
FROM potential_clients crm
JOIN customer_table ag ON ( crm.company = ag.company)
GROUP BY crm.company HAVING COUNT(*) >= 1
Und hier liegt der "Hund" begraben -> JOIN ... ON ( crm.company =
ag.company)!
Ich müsste an dieser Stelle sowas wie ein crm.company LIKE
'%ag.company%' haben. Aber wie genau muss ich dies schreiben?
Wie das geht, weißt Du ja jetzt. Dass MySQL wg. des führenden "%" im
LIKE dann keinen Index benutzt, auch.

Jetzt noch das: Wenn der Firmenname nicht "100% korrekt" eingegeben
wurde, dann hilft dieses LIKE exakt gar nicht. Das findet nämlich Dinge
wie "Maier" vs. "Meyer" ebenso wenig wie "Müller Ingenieur GmbH" vs.
"Müller Ingges. mbH".

Namen sind für das Finden von Dubletten keine besonders guten
Indikatoren. Postleitzahl + Straße eignen sich wesentlich besser, denn
bei beiden sind die Freiheitsgerade geringer. Ich benutze so eine
Prüfung schon bei der Eingabe, um eben Dubletten zu verhindern.
Ben Butschko
2009-03-10 09:56:09 UTC
Permalink
Post by Christian Kirsch
Wie das geht, weißt Du ja jetzt. Dass MySQL wg. des führenden "%" im
LIKE dann keinen Index benutzt, auch.
Danke, das habe ich bis dato tasächlich nicht gewusst :-/
Post by Christian Kirsch
Jetzt noch das: Wenn der Firmenname nicht "100% korrekt" eingegeben
wurde, dann hilft dieses LIKE exakt gar nicht. Das findet nämlich Dinge
wie "Maier" vs. "Meyer" ebenso wenig wie "Müller Ingenieur GmbH" vs.
"Müller Ingges. mbH".
Das sehe ich auch so. Jedoch will mein Chef diesen Abgleich und diese
Argumentation hatte ich ihm nahegelegt.
Post by Christian Kirsch
Namen sind für das Finden von Dubletten keine besonders guten
Indikatoren. Postleitzahl + Straße eignen sich wesentlich besser, denn
bei beiden sind die Freiheitsgerade geringer. Ich benutze so eine
Prüfung schon bei der Eingabe, um eben Dubletten zu verhindern.
Das Problem hierbei ist, das auf einer Adresse mit gleicher Straße und
sogar gleicher Hausnummer mehrere Unternehmen / Agenturen sitzen können.
Das kommt bei unserem Kundenstamm häufiger vor.

Danke für Deine Anmerkungen und netten Gruß
Ben
Christian Kirsch
2009-03-10 10:10:14 UTC
Permalink
Post by Ben Butschko
Das Problem hierbei ist, das auf einer Adresse mit gleicher Straße und
sogar gleicher Hausnummer mehrere Unternehmen / Agenturen sitzen können.
Das kommt bei unserem Kundenstamm häufiger vor.
Klar. Die Anwendung soll sich ja auch nicht weigern, sondern dem
Benutzer sagen "Hey, da gibt's schon die Firmen A, B und C an dieser
Adresse - willst Du wirklich D eintragen?" Automatismen helfen da wenig.
Axel Schwenke
2009-03-10 09:57:19 UTC
Permalink
Post by Ben Butschko
Ich möchte mögliche Doubletten aus zwei Tabellen ermitteln.
Dazu verwende ich JOIN.
Nun kann es aber sein, dass der Firmenname von einem Benutzer X nicht
100% korrekt in die Datenbank gespeichert wurde - sprich ich müsste ein
LIKE verwenden.
Damit wirst du eher wenig Erfolg haben, weil LIKE schon Standard-
Vertipper wie Maier vs. Meier nicht korrigieren kann. Für den
englischen Sprachraum gibt es die SOUNDEX() Funktion, die den
Vergleich von Strings auf der Basis "klingt gleich" ermöglicht.

Siehe SOUNDEX() und SOUNDS LIKE im MySQL-Manual:
http://dev.mysql.com/doc/refman/5.0/en/string-functions.html#function_soundex

Wie gesagt ist SOUNDEX() allerdings auf englische Strings geeicht.
Im Deutschen sind die Ergebnisse eher bescheiden.

Erfolgversprechender ist ein Ähnlichkeitsmaß auf Basis von
->Trigramm-Statistiken, allerdings gibts das in MySQL nicht.

Nette Übersicht:
http://www.tillmann-wegst.de/fuzzy/index.htm


XL
Loading...