2011-03-31 16 views
5

में शब्द मिलान मुझे दो डेटाबेस तालिकाओं में डेटा के बीच एक सुझाए गए मैच प्रदान करने की आवश्यकता है। मूल आवश्यकता है; - प्रश्न में दो स्तंभों के बीच मिलान किए गए शब्दों की संख्या (चाहे ऑर्डर के बावजूद) के लिए "मैच" का सुझाव दिया जाना चाहिए।एसक्यूएल सर्वर

उदाहरण के लिए, डेटा दिया गया;

Table A       Table B 
1,'What other text in here'  5,'Other text in here' 
2,'What am I doing here'   6,'I am doing what here' 
3,'I need to find another job' 7,'Purple unicorns' 
4,'Other text in here'   8,'What are you doing in here' 

Ideally, my desired matches would look as follows; 
1 -> 8 (3 words matched) 
2 -> 6 (5 words matched) 
3 -> Nothing 
4 -> 5 (4 words matched) 

मैं word count functions कि आशाजनक लग पाया है, लेकिन मैं कैसे एक SQL विवरण में इसका इस्तेमाल करने की सोच भी नहीं सकते, कि मुझे मेरी वांछित मैच दे देंगे। साथ ही, लिंक किए गए फ़ंक्शन को काफी कुछ नहीं है क्योंकि यह charindex का उपयोग करता है जो मुझे लगता है कि एक शब्द के भीतर एक शब्द की खोज करता है (यानी 'इन' 'मिलान' बिन ')।

क्या कोई इस के साथ मेरी मदद कर सकता है ??

धन्यवाद।

+0

3 मैचों 6. दोनों शब्द "मैं" है। और 1 मैच 8 से बेहतर 5। वे 4 शब्दों को साझा करते हैं। –

+0

आप सही हैं, लेकिन मैं यह उल्लेख करना भूल गया कि मैचों में कोई डुप्लीकेट नहीं होना चाहिए। एक बार दी गई पंक्ति मिलान हो जाने पर, इसे फिर से मिलान नहीं किया जा सकता है। आप 5 मिलान 8 के बारे में भी सही हैं, लेकिन जैसा कि मैंने अभी आपके उत्तर पर टिप्पणी की है, यह आदर्श रूप से मेल खाने वाले समग्र शब्दों के प्रतिशत को ध्यान में रखना चाहिए। –

उत्तर

5

मैंने वाक्य में वाक्यों को विभाजित करने के लिए नीचे sys.dm_fts_parser का उपयोग किया है। plenty of TSQL split functions around हैं यदि आप SQL Server 2008 पर नहीं हैं या पाते हैं कि यह किसी कारण से उपयुक्त नहीं है।

प्रत्येक A.id प्रत्येक आवश्यकता को केवल B.id के साथ जोड़ा जा सकता है जिसका उपयोग पहले नहीं किया गया था और इसके विपरीत मैं एक कुशल सेट आधारित समाधान के बारे में सोच सकता हूं।

;WITH A(Id, sentence) As 
(
    SELECT 1,'What other text in here' UNION ALL 
    SELECT 2,'What am I doing here'  UNION ALL 
    SELECT 3,'I need to find another job' UNION ALL 
    SELECT 4,'Other text in here'   
), 
B(Id, sentence) As 
(
SELECT 5,'Other text in here'   UNION ALL 
SELECT 6,'I am doing what here'  UNION ALL 
SELECT 7,'Purple unicorns'    UNION ALL 
SELECT 8,'What are you doing in here' 
), A_Split 
    AS (SELECT Id AS A_Id, 
       display_term, 
       COUNT(*) OVER (PARTITION BY Id) AS A_Cnt 
     FROM A 
       CROSS APPLY 
        sys.dm_fts_parser('"' + REPLACE(sentence, '"', '""')+'"',1033, 0,0)), 

    B_Split 
    AS (SELECT Id AS B_Id, 
       display_term, 
       COUNT(*) OVER (PARTITION BY Id) AS B_Cnt 
     FROM B 
       CROSS APPLY 
        sys.dm_fts_parser('"' + REPLACE(sentence, '"', '""')+'"',1033, 0,0)), 
    Joined 
    As (SELECT A_Id, 
       B_Id, 
       B_Cnt, 
       Cnt = COUNT(*), 
       CAST(COUNT(*) as FLOAT)/B_Cnt AS PctMatchBToA, 
       CAST(COUNT(*) as FLOAT)/A_Cnt AS PctMatchAToB 
     from A_Split A 
       JOIN B_Split B 
        ON A.display_term = B.display_term 
     GROUP BY A_Id, 
        B_Id, 
        B_Cnt, 
        A_Cnt) 
SELECT IDENTITY(int, 1, 1) as id, * 
INTO #IntermediateResults 
FROM Joined 
ORDER BY PctMatchBToA DESC, 
      PctMatchAToB DESC 

DECLARE @A_Id INT, 
     @B_Id INT, 
     @Cnt INT 

DECLARE @Results TABLE (
    A_Id INT, 
    B_Id INT, 
    Cnt INT) 

SELECT TOP(1) @A_Id = A_Id, 
       @B_Id = B_Id, 
       @Cnt = Cnt 
FROM #IntermediateResults 
ORDER BY id 

WHILE (@@ROWCOUNT > 0) 
    BEGIN 

     INSERT INTO @Results 
     SELECT @A_Id, 
      @B_Id, 
      @Cnt 

     DELETE FROM #IntermediateResults 
     WHERE A_Id = @A_Id 
       OR B_Id = @B_Id 

     SELECT TOP(1) @A_Id = A_Id, 
        @B_Id = B_Id, 
        @Cnt = Cnt 
     FROM #IntermediateResults 
     ORDER BY id 
    END 

DROP TABLE #IntermediateResults 

SELECT * 
FROM @Results 
ORDER BY A_Id 

रिटर्न

A_Id  B_Id  Cnt 
----------- ----------- ----------- 
1   8   3 
2   6   5 
4   5   4 
+0

वाह! मैंने सोचा कि एसक्यूएल के बारे में एक या दो चीज़ों को पता था, लेकिन आपने अभी बताया है कि ऐसी कई चीजें हैं जिन्हें मैं नहीं जानता :) यह निश्चित रूप से वास्तव में सहायक है। एक बात जो मैं उल्लेख करना भूल गया था वह यह है कि मैचों में कोई डुप्लीकेट नहीं होना चाहिए। वास्तव में मिलान किए गए शब्दों के उच्चतम प्रतिशत वाले मैच को प्राथमिकता लेनी चाहिए। यही कारण है कि मेरे उदाहरण में, मेरे पास 4 से 4 मिलान था क्योंकि पाठ बराबर (100% मैच) था, और इसलिए 8 के साथ मैच के लिए 1 छोड़ देता है क्योंकि यह अगला सबसे अच्छा मैच है। हालांकि मुझे वास्तव में आपका जवाब पसंद है। यह विचार के लिए बहुत अच्छा खाना है। आपके लिए +1 .... अगर मुझे कोई प्रतिष्ठा है। –

+0

@ एमआर मूस: क्या तुम नहीं हो? :) @ मार्टिन: हालांकि यह तब से कहा गया है कि एक पंक्ति केवल एक से अधिक बार मेल नहीं खाई जा सकती है, मुझे अभी भी लगता है कि आपका समाधान उपयोगी है। और यहां तक ​​कि यदि आप इसे फिर से काम नहीं कर रहे हैं, तो यह शुरू करने के लिए एक अच्छा है। –

+0

@Andriy - धन्यवाद। मैं इसे फिर से काम कर सकता हूं। "ROW_NUMBER() से अधिक (A_Id द्वारा विभाजित ... 'को शीर्ष 1 प्रति ए और' ROW_NUMBER() ओवर (बी_आईडी द्वारा विभाजित ...' प्राप्त करने के लिए पर्याप्त है, प्रति बी 1 शीर्ष प्राप्त करने के लिए, लेकिन इसके भागने से मुझे दो संयोजन के एक अच्छे तरीके के पल में। –

संबंधित मुद्दे