2011-01-12 13 views
30
$word = strtolower($_GET['term']); 

$lev = 0; 

$q = mysql_query("SELECT `term` FROM `words`"); 
while($r = mysql_fetch_assoc($q)) 
{ 
    $r['term'] = strtolower($r['term']); 

    $lev = levenshtein($word, $r['term']); 

    if($lev >= 0 && $lev < 5) 
    { 
     $word = $r['term']; 
    } 
} 

मैं इसे केवल एक प्रश्न में कैसे ले जा सकता हूं? सभी शर्तों के माध्यम से पूछना नहीं चाहते हैं और PHP में फ़िल्टरिंग करना चाहते हैं।लेवेनशेटिन: MySQL + PHP

उत्तर

56

आप एक levenshtein function in MySQL और

जैसी क्वेरी
$word = mysql_real_escape_string($word); 
mysql_qery("SELECT `term` FROM `words` WHERE levenshtein('$word', `term`) BETWEEN 0 AND 4"); 
+2

ऊपर दिए गए प्रश्न तब तक असफल हो जाएंगे जब तक आप पहले एसक्यूएल डिलीमीटर नहीं बदलते। प्रश्नों से पहले 'DELIMITER @' का उपयोग करें, प्रत्येक क्वेरी दर्ज करने के बाद अपना नया @ डिलीमीटर जोड़ें, फिर अपने डिलीमीटर को वापस 'DELIMITER;' –

+6

के साथ बदलें, क्या यह बड़े डेटा सेट के विरुद्ध चलने के लिए उपयुक्त है? मैं 458546 रिकॉर्ड के खिलाफ LEVENSHTEIN चलाने की कोशिश कर रहा हूं, क्वेरी प्रतिक्रिया नहीं दे रही है। – vishal

+0

जब मैं फ़ंक्शन बनाने का प्रयास करता हूं तो मुझे एक त्रुटि मिलती है: # 1064 - आपको अपने SQL वाक्यविन्यास में कोई त्रुटि है; लाइन 5 पर '' के पास उपयोग करने के लिए सही वाक्यविन्यास के लिए आपके MySQL सर्वर संस्करण से मेल खाने वाले मैन्युअल की जांच करें क्या कोई पूरी तरह से काम कर रहे कोड को पास कर सकता है? –

-4

यह एक प्रश्न है। यदि आप पूछ रहे हैं कि क्या आप lesshtein कार्यक्षमता को mysql पर ले जा सकते हैं, तो आप नहीं कर सकते हैं।

ठीक है, ठीक है आप कर सकते हैं, लेकिन यह php में ऐसा करने से कहीं अधिक आसान नहीं है।

http://www.artfulsoftware.com/infotree/queries.php?&bw=1280#552

0

मैं एक समारोह है कि कहा जा सकता है अंदर PL/SQL में एल्गोरिथ्म को लागू करने से Oracle में यह करते हैं।

+0

उत्कृष्ट, तो आप हमें क्या कह रहे हैं कि इस समस्या को कुछ कोड की आवश्यकता है! – Drumbeg

+0

सॉर्टा- हाँ - प्रश्न 'एक प्रश्न में' समाधान को कैसे व्यवस्थित करना है, इस बारे में सवाल था - मैं सलाह को जटिल बनाने के लिए एक फ़ंक्शन में जटिलता को स्थानांतरित करने की सलाह देता हूं। – Randy

+0

यदि आप हमें कोड आ सकते हैं तो यह बहुत अच्छा होगा। – Drumbeg

1

आप इस कोड कर सकते हैं की जरूरत है थोड़ा neater देखो लेकिन @profitphp सही है, तो आप नहीं यह MySQL में एक levenstein पुस्तकालय के बिना कर सकते हैं।

 
$word = strtolower($_GET['term']); 

$q = mysql_uqery("SELECT LOWER(`term`) FROM `words`"); 

while($r = mysql_fetch_assoc($q)) { 

    $lev = levenshtein($word, $r['term']); 

    .... 

} 
11

MySQL में लेवेनशेटिन फ़ंक्शन को लागू करने के दो तरीके हैं। पहला एक स्टोर्ड फ़ंक्शन बनाना है जो एक स्टोर्ड ट्रांज़ेक्शन की तरह काम करता है, सिवाय इसके कि इसमें अलग इनपुट और आउटपुट है। यह छोटे डेटासेट के लिए ठीक है, लेकिन कई हजार पंक्तियों के करीब कुछ भी धीमा है।

एक sql फ़ाइल में
CREATE FUNCTION levenshtein(s1 VARCHAR(255), s2 VARCHAR(255)) 
RETURNS INT 
DETERMINISTIC 

BEGIN 
DECLARE s1_len, s2_len, i, j, c, c_temp, cost INT; 
DECLARE s1_char CHAR; 
-- max strlen=255 
DECLARE cv0, cv1 VARBINARY(256); 
SET s1_len = CHAR_LENGTH(s1), s2_len = CHAR_LENGTH(s2), cv1 = 0x00, j = 1, i = 1, c = 0; 
IF s1 = s2 THEN 
    RETURN 0; 
ELSEIF s1_len = 0 THEN 
    RETURN s2_len; 
ELSEIF s2_len = 0 THEN 
    RETURN s1_len; 
ELSE 
    WHILE j <= s2_len DO 
    SET cv1 = CONCAT(cv1, UNHEX(HEX(j))), j = j + 1; 
    END WHILE; 
    WHILE i <= s1_len DO 
    SET s1_char = SUBSTRING(s1, i, 1), c = i, cv0 = UNHEX(HEX(i)), j = 1; 
    WHILE j <= s2_len DO 
    SET c = c + 1; 
    IF s1_char = SUBSTRING(s2, j, 1) THEN 
     SET cost = 0; ELSE SET cost = 1; 
    END IF; 
    SET c_temp = CONV(HEX(SUBSTRING(cv1, j, 1)), 16, 10) + cost; 
    IF c > c_temp THEN SET c = c_temp; END IF; 
     SET c_temp = CONV(HEX(SUBSTRING(cv1, j+1, 1)), 16, 10) + 1; 
     IF c > c_temp THEN 
     SET c = c_temp; 
     END IF; 
     SET cv0 = CONCAT(cv0, UNHEX(HEX(c))), j = j + 1; 
    END WHILE; 
    SET cv1 = cv0, i = i + 1; 
    END WHILE; 
END IF; 

RETURN c; 

END// 

स्टोर ऊपर कोड और इसे आयात अपने डेटाबेस में इतनी तरह:

source /tmp/mysql_udf.sql 

दूसरी विधि सी/C++ एक उपयोगकर्ता निर्धारित समारोह को लागू करने और लिंक में करने के लिए है एक साझा लाइब्रेरी (* .so फ़ाइल) के रूप में MySQL। यह विधि लाइब्रेरी को कॉल करने के लिए एक स्थिर फ़ंक्शन का भी उपयोग करती है, जिसका अर्थ है कि इस के लिए वास्तविक क्वेरी या पहली विधि समान हो सकती है (दोनों कार्यों में इनपुट प्रदान करना समान है)। आप इस विधि के बारे में यहाँ और अधिक जानकारी प्राप्त कर सकते हैं: कुछ http://samjlevy.com/mysql-levenshtein-and-damerau-levenshtein-udfs/

इन तरीकों में से किसी के साथ, आपकी क्वेरी होगा जैसे:

SELECT term FROM words WHERE levenshtein(term, 'term') < 5; 

भी ध्यान रखें कि 'सीमा' मूल्य के संबंध में बदलना चाहिए मूल शब्द लंबाई। प्रतिशत मूल्य के संदर्भ में इसके बारे में सोचना बेहतर है, यानी आपका शब्द = 50%, आधे शब्द '='

+0

उपरोक्त पहला लिंक (http://kristiannissen.wordpress.com/2010/07/08/mysql-levenshtein/) अब सक्रिय नहीं है। – bwright

+0

प्रासंगिक सामग्री के साथ लिंक को प्रतिस्थापित करने के लिए संपादित किया गया। बेहतर? :) –

7

यदि आपके पास एक विशाल डेटाबेस है, तो आप पहले SOUNDEX का उपयोग करके शब्दों को फ़िल्टर कर सकते हैं:

$word = strtolower(mysql_real_escape_string($_GET['term'])); 

$rs = mysql_query("SELECT LOWER(`term`) FROM `words` WHERE SOUNDEX(term) = SOUNDEX(" . $word . ")"); 

while ($row = mysql_fetch_assoc($rs)) { 

    $lev = levenshtein($word, $row['term']); 

    .... 

} 

यदि आपके पास पर्याप्त समय एक सी विस्तार या प्रक्रिया के साथ खेलने के लिए है, तो आप अपना प्रदर्शन सुधार सकते हैं, लेकिन असली Levenshtein लागू करने के लिए तेजी से लगभग कोई प्रयास के साथ बातें कर देगा से पहले mysql पर रिकॉर्ड को छानने।

5

यदि आप बहुत बड़े डेटा सेट से निपट रहे हैं तो मुझे पता चला है कि यह लेवेनशेटिन संचालन को संभालने और PHP में सॉर्ट करने के लिए MySQL में सॉर्ट करने के लिए और अधिक कुशल है। उदा। लगभग 1000 अभिलेखों की क्वेरी:

MySQL (~ 0.0050s) -> पीएचपी Levenshtein (~ 1.300s)

बनाम

MySQL Levenshtein (> = 5.000s) -> पीएचपी (~ 0.250s)

वहाँ भी खोज इंजन अनुकूलन के लिए कई अन्य विकल्प हैं, लेकिन आप Levenshtein उपयोग करना चाहते हैं तो बस डेटा आप हूँ के बारे में पता होना हैंडलिंग और आप चाहते हैं कि विलंबता।

1

मेरा सुझाव है कि आप लेवेनशेटिन (लिंक: http://www.artfulsoftware.com/infotree/queries.php#552) की कॉल सहित आपकी क्वेरी में शामिल हैं।

आपको mysqli_query ($ q) का उपयोग करना चाहिए क्योंकि mysql_query ($ q) को बहिष्कृत किया गया है और भविष्य में PHP संस्करणों में हटाया जा सकता है!

$word = mysql_real_escape_string($word); 
$query = "SELECT `term` FROM `words` WHERE levenshtein('$word', `term`) BETWEEN 0 AND 4"; 
mysqli_qery($query);