Wie kan mij helpen met het volgende vraagstuk:
Ik moet een stukje programma schrijven dat namen kan 'matchen'. De situatie is als volgt:
Aan de ene kant heb ik een lijst met bedrijven in een database. Aan de andere kant een CSV file.
Het eindresultaat na het uitvoeren van het stukje programma is dat ik een CSV bestand wil hebben met alle bedrijven die voorkomen in zowel de CSV als de MySQL database, met daarbij de door de gebruiker geselecteerde gegevens uit de CSV en/of de Database. De selectie van kolommen is op dit moment geen probleem.
• In de mysql database heb ik 20.000 bedrijven staan, met NAW gegevens en nog een aantal intern gebruikte codes. Dit aantal, 20.000, kan nog behoorlijk groeien.
• In het CSV bestand staat minimaal een bedrijfsnaam, en optioneel nog meer kolommen die niet in de mysql database voorkomen. In het csv bestand staan gemiddeld 1500 records
Wat er nu moet gebeuren is het matchen van deze twee gegevensbronnen. Ik kan dus alleen matchen op bedrijfsnaam. Het probleem is echter dat er niet 1 op 1 te matchen valt, omdat de schrijfwijze van de bedrijfsnamen nogal verschillend kan zijn.
Wat ik heb verzonnen is een functie die gebruikmaakt van de levenshtein functie in PHP. Een SELECT-query haalt alle records uit de database, en terwijl door het result wordt gelopen, wordt elk record tegen elk record in de csv gematcht. De functie wordt dus 20.000 x 1.500 = 30.000.000 keren aangeroepen. Deze methode werkt (bij kleinere aantallen), maar et zal jullie niet verbazen dat deze methode veel en veel te lang duurt.
De functie die ik heb gemaakt:
Pseudo-code die door de gegevens heenloopt:
Ik weet niet of het zin heeft om de genoemge functies te optimaliseren, ik denk dat er een andere insteek voor de oplossing van het probleem moet komen.
Wat ik verder nog geprobeerd heb is in de database de eerste 2 en de laatste 2 tekens van een bedrijfsnaam op te slaan en daarmee een soort voorselectie creeeren. Door de verschillende schrijfwijzen is dit niet mogelijk.
Een aantal voorbeelden van gematchte bedrijfsnamen die in het doelbestand moeten komen:
Ik ben benieuwd of er iets te bedenken valt voor dit probleem, of dat men de gegevens maar moet gaan nettoyeren.
Ik moet een stukje programma schrijven dat namen kan 'matchen'. De situatie is als volgt:
Aan de ene kant heb ik een lijst met bedrijven in een database. Aan de andere kant een CSV file.
Het eindresultaat na het uitvoeren van het stukje programma is dat ik een CSV bestand wil hebben met alle bedrijven die voorkomen in zowel de CSV als de MySQL database, met daarbij de door de gebruiker geselecteerde gegevens uit de CSV en/of de Database. De selectie van kolommen is op dit moment geen probleem.
• In de mysql database heb ik 20.000 bedrijven staan, met NAW gegevens en nog een aantal intern gebruikte codes. Dit aantal, 20.000, kan nog behoorlijk groeien.
• In het CSV bestand staat minimaal een bedrijfsnaam, en optioneel nog meer kolommen die niet in de mysql database voorkomen. In het csv bestand staan gemiddeld 1500 records
Wat er nu moet gebeuren is het matchen van deze twee gegevensbronnen. Ik kan dus alleen matchen op bedrijfsnaam. Het probleem is echter dat er niet 1 op 1 te matchen valt, omdat de schrijfwijze van de bedrijfsnamen nogal verschillend kan zijn.
Wat ik heb verzonnen is een functie die gebruikmaakt van de levenshtein functie in PHP. Een SELECT-query haalt alle records uit de database, en terwijl door het result wordt gelopen, wordt elk record tegen elk record in de csv gematcht. De functie wordt dus 20.000 x 1.500 = 30.000.000 keren aangeroepen. Deze methode werkt (bij kleinere aantallen), maar et zal jullie niet verbazen dat deze methode veel en veel te lang duurt.
De functie die ik heb gemaakt:
PHP:
1
2
3
4
5
6
7
8
9
10
11
12
| <? function nameScore($input1,$input2) { $input1 = str_replace(array("bv","b.v.","nv","n.v."),"",strtolower($input1)); $input2 = str_replace(array("bv","b.v.","nv","n.v."),"",strtolower($input2)); $score = levenshtein($input1,$input2); $num_chars = round(strlen($input1) + strlen($input2) /2); return round(pow(((1-($score/$num_chars))*100),2)*0.05); } ?> |
Pseudo-code die door de gegevens heenloopt:
code:
1
2
3
4
5
6
7
| $data = array, 1 regel CSV per arrayelement while ($get = mysql_Fetch_object($query)) { for ($i=0;$i<sizeof($data);$i++) { $score = nameScore($data[$i]['naam'],$get->naam); als score > 185 registreer dat de match correct is } } |
Ik weet niet of het zin heeft om de genoemge functies te optimaliseren, ik denk dat er een andere insteek voor de oplossing van het probleem moet komen.
Wat ik verder nog geprobeerd heb is in de database de eerste 2 en de laatste 2 tekens van een bedrijfsnaam op te slaan en daarmee een soort voorselectie creeeren. Door de verschillende schrijfwijzen is dit niet mogelijk.
Een aantal voorbeelden van gematchte bedrijfsnamen die in het doelbestand moeten komen:
code:
1
2
3
| DUIJVELAAR POMPEN BV - DP Pumps/Duijvelaar Pompen GERARD VINK STANDBOUW - Vink Standbouw b.v. DONNER BOEKEN BV - PS Games Donner Boeken |
Ik ben benieuwd of er iets te bedenken valt voor dit probleem, of dat men de gegevens maar moet gaan nettoyeren.