我有一个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字符串函数,但是没有发现任何对我来说简单的东西解。提前感谢您的帮助!
答案 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。然后使用该表我将字符串及其索引分开。
然后我加入它自己并寻找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