MySQL在每个列记录中获得子串匹配计数

时间:2014-09-05 19:19:04

标签: mysql sql string substring match

我有一个mysql表,其中包含一个包含6个字符串(varchar(6))的列(代码)。该列的示例记录将是:

ID      code
1       ADHNQS
2       BDHLQS
3       AEGMQS

我需要做的是一次比较1个代码记录,然后检索“相关代码”。如果相关代码包含4个或更多相同字符,则相关代码将符合条件。例如:

ADHNQS - > BDHLQS 将匹配,因为D,H,Q,S是共享的,并且是4或更高。

ADHNQS - > BCHLQR 不会匹配,因为他们的共享字符小于4。

如何在SQL中检索一组所有记录,并且它们的字符匹配计数是4还是更大?我已经查看了很多MYSQL字符串函数,但是没有发现任何对我来说简单的东西解。提前感谢您的帮助!

4 个答案:

答案 0 :(得分: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 

答案 1 :(得分: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次比较。 (比较pos 1到pos 1,2,3,4,5,6,比较pos 2和pos 1,2,3,4,5,6)

这可以与上面的查询完全相同,只是 AND ( ) >= 4 谓词将包含总共36个比较测试,而不是仅包含六个。

这会(再次)出现字符串中相同字符的倍数问题,以及如何将这些问题“计入”匹配。例如,考虑:

code1: QbQdef
code2: QxyQQz

code1的位置1中的Q匹配code2中的三个Q,code1的位置2中的Q也匹配code2中的三个Q ...总匹配数为6.我们是否要将这两个代码视为匹配?如果没有,我们可以稍微修改查询中的测试块,这样位置1中的字符与code2中任何字符的匹配将导致只有1被添加到匹配计数中。

需要更多地充实规范,以便确定实现所需结果的实际SQL语句。

答案 2 :(得分:1)

@ spencer7593有一个非常好的sql语句,当varchar位置相同时可以工作。

但是如果你想用php解决这个问题并且char位置并不总是相同的:

$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;

注意:这个问题的一个问题是字符串是否有重复的字符。必须有一些额外的逻辑。问题没有显示,所以我没有添加它。

答案 3 :(得分: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