2014-09-05 51 views
1

我有一個包含6個字符串(varchar(6))的列(代碼)的mysql表。該列的示例記錄是:MySQL獲取每列記錄中的子串匹配計數

ID  code 
1  ADHNQS 
2  BDHLQS 
3  AEGMQS 

我需要做的是在一個時間比較1碼記錄到休息和恢復「相關的代碼」。如果相關代碼包含4個或更多相同字符,則該代碼將符合條件。例如:

ADHNQS - > BDHLQS將是一個匹配,因爲D,H,Q,S是共享的,並且是4或更大。

ADHNQS - > BCHLQR不會是一個比賽,因爲他們共同的字符小於4

我怎樣才能與他們的性格匹配計數SQL檢索一組的所有記錄,他們是4或更高?我研究了許多MYSQL字符串函數,但沒有發現任何可以作爲簡單解決方案跳出來的東西。預先感謝您的幫助!

+0

你確定你想這樣做在SQL查詢,而不是一個標準的編程語言? – Jay 2014-09-05 19:21:20

+0

我寧願在sql中比在php中執行它,是的。 – 2014-09-05 19:27:02

+0

有字符串函數來查看每個字符(SUBSTRING) - 但是你必須爲每個4個匹配的排列創建一個CASE - 並且有很多。否則,你會在腳本語言中更好地在MYSQL之外做它。 – user3741598 2014-09-05 19:30:23

回答

2

如果你只是有你的參考行的ID(這裏:1):

SELECT b.ID, b.code, 
(if(substring(b.code,1,1)=substr(a.code,1,1),1,0) + if(substring(b.code,2,1)=substr(a.code,2,1),1,0) + if(substring(b.code,3,1)=substr(a.code,3,1),1,0) + if(substring(b.code,4,1)=substr(a.code,4,1),1,0) + if(substring(b.code,5,1)=substr(a.code,5,1),1,0) + if(substring(b.code,6,1)=substr(a.code,6,1),1,0)) as matchcount 
FROM yourtablename as a, yourtablename as b 
WHERE a.ID=1 
AND b.ID<>a.ID 
GROUP BY 1 
HAVING matchcount>=4 
ORDER BY matchcount desc 

返回:

ID code matchcount 
2 BDHLQS 4 


如果你只需要代碼(位置:ADHNQS)那麼你可以像這樣手動建立你的查詢(如果存在,將返回你的確切代碼):

SELECT ID, code, 
(if(substring(code,1,1)="A",1,0) + if(substring(code,2,1)="D",1,0) + if(substring(code,3,1)="H",1,0) + if(substring(code,4,1)="N",1,0) + if(substring(code,5,1)="Q",1,0) + if(substring(code,6,1)="S",1,0)) as matchcount 
FROM yourtablename 
GROUP BY 1 
HAVING matchcount>=4 
ORDER BY matchcount desc 

退貨:

ID code matchcount 
1 ADHNQS 6 
2 BDHLQS 4 
+0

非常簡單的答案,遵循,並完美工作。謝謝! – 2014-09-05 20:22:50

1

在示例「匹配」中,匹配的字符在兩個字符串中都處於相同的位置。目前尚不清楚這是否是實際的規格,或者如果這只是示例中的異常情況。另外,我們注意到,在示例數據中,字符列表是不同的,任何字符串中都沒有兩個相同的字符。再次,不確定這是規範的一部分,還是示例中的異常。

此外,代碼值的長度始終是六個字符?對較短的字符串或空格字符進行特殊處理?等


在最簡單的情況下,如果我們通過排名來比較字符串位置,唯一的要求就是一個字等於另一個字符(無特殊處理的空間,或者非字母,等),那麼像這樣將返回指定的結果:

SELECT c.id 
    , c.code 
    , d.id 
    , d.code 
    FROM mytable c 
    JOIN mytable d 
    ON d.id <> c.id 
    AND (IFNULL(NULLIF(SUBSTR(c.code,1,1),'') = NULLIF(SUBSTR(d.code,1,1),'') ,0) 
     + IFNULL(NULLIF(SUBSTR(c.code,2,1),'') = NULLIF(SUBSTR(d.code,2,1),'') ,0) 
     + IFNULL(NULLIF(SUBSTR(c.code,3,1),'') = NULLIF(SUBSTR(d.code,3,1),'') ,0) 
     + IFNULL(NULLIF(SUBSTR(c.code,4,1),'') = NULLIF(SUBSTR(d.code,4,1),'') ,0) 
     + IFNULL(NULLIF(SUBSTR(c.code,5,1),'') = NULLIF(SUBSTR(d.code,5,1),'') ,0) 
     + IFNULL(NULLIF(SUBSTR(c.code,6,1),'') = NULLIF(SUBSTR(d.code,6,1),'') ,0) 
     ) >= 4 
WHERE c.id = 1 
ORDER BY c.id, d.id 

如果我們需要每一個字符code比較各自在對方code的人物,我們就會有類似的東西,我們剛剛需要執行總共36次比較。 (比較位置1至位置 1,2,3,4,5,6,比較位置2至位置1,2,3,4,5,6)

這可以與查詢完全相同除了謂詞將包含總共36個比較測試,而不僅僅是6個。

這會再次引發字符串中同一字符的倍數問題,以及如何將這些字符「計算」爲匹配。例如,考慮:

code1: QbQdef 
code2: QxyQQz 

將q在編碼1 1位置碼2匹配三問的,並在編碼1的2位Q也會匹配三問在代碼2 ...爲6總比賽數。我們是否想將這兩個代碼視爲匹配?如果沒有,我們可以稍微修改查詢中的測試塊,以便將位置1中的字符與代碼2中的任何字符進行匹配,只會將1添加到匹配計數中。

爲了確定實現所需結果的實際SQL語句,需要充實更多的規範。

1

@ spencer7593有一個非常長的漂亮的sql語句,當varchar位置相同時工作。

,但如果你想解決這個問題,PHP和焦炭位置並不總是相同的:

$string1 = 'SOMESTRING'; 
$stringAsArray = str_split($string1); 
sort($stringAsArray); 

$string2 = "ASDFOMKHRG"; 
$string2AsArray = str_split($string2); 

$count = 0; 
foreach($stringAsArray as $value){ 
    foreach($string2AsArray as $value2){ 
     if($value == $value2) count+=1; 
    } 
} 
if(count >= 4) return string2; 

注:與這雖然一個問題是,如果字符串有重複的字符。必須有一些額外的邏輯。沒有顯示的問題,所以我沒有添加它。

+0

謝謝,我特別尋找SQL解決方案。我已經能夠在PHP中做到這一點:)雖然感激! – 2014-09-05 20:15:22

0

這看起來很有趣,所以我給了它一個鏡頭。首先,我建立了一個數字表,字面上只有1-15個數字。然後使用該表將分割字符串及其索引。

Base table

然後我加入,爲自己和尋找的4個或更多的比賽。從理論上講,只要你的數字表足夠大,這應該適用於任何字符串長度。

select a2.code 
from 
    (
    select *, 
     SUBSTRING(t.code, n.num, 1) as 'Character' 
    from numbers n 
    join test t 
     on length(t.code) >= n.num 
) a1 
join 
    (
    select *, 
     SUBSTRING(t.code, n.num, 1) as 'Character' 
    from numbers n 
    join test t 
     on length(t.code) >= n.num 
    ) a2 on a1.character = a2.character and a1.id <> a2.id 
where a1.id = 1 
group by a2.code having count(1) >= 4 

這裏的SQL Fiddle Demo