Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/algorithm/12.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
MySQL计数列中出现的子字符串数_Mysql - Fatal编程技术网

MySQL计数列中出现的子字符串数

MySQL计数列中出现的子字符串数,mysql,Mysql,使用MySQL,我试图计算每一行的子字符串在列中出现的次数 在下面的示例表中,字符串“art”在“术语”列中出现三次,因此其计数为3 示例表: TERMS art artistic painting elephant art deco paint paintings 期望输出: TERMS COUNT art 3 artistic 1 painting 2 elephant 1 art deco 1 paint 2 paintings 1

使用MySQL,我试图计算每一行的子字符串在列中出现的次数

在下面的示例表中,字符串“art”在“术语”列中出现三次,因此其计数为3

示例表:

TERMS
art
artistic
painting
elephant
art deco
paint
paintings
期望输出:

TERMS      COUNT
art        3
artistic   1
painting   2
elephant   1
art deco   1
paint      2
paintings  1
编辑:

作为起点,我知道:

SELECT terms, COUNT(*)
FROM table
GROUP BY terms
将输出每个完整术语字符串的出现次数。对于子字符串匹配,我认为这可能涉及子查询

尝试了以下操作,但每次计数均为1

SELECT terms, ROUND((CHAR_LENGTH(terms) - CHAR_LENGTH(REPLACE(terms, terms, ""))) / CHAR_LENGTH(terms)) AS count
FROM table
GROUP BY terms

我首先编写一个查询,返回我们想要返回的术语列表。例如:

 SELECT t.terms
   FROM `table` t
  GROUP BY t.terms
然后将其包装在parens中,并将其用作内联视图

SELECT w.terms
  FROM ( SELECT t.terms
           FROM `table` t
          GROUP BY t.terms
       ) w
 ORDER BY w.terms
这样,我们就可以执行联接操作来查找匹配的行,并获得一个计数。假设保证
术语
不包含下划线(
\uu
)或百分比(
%
)字符,我们可以使用类似于的
比较

考虑到列表中的每个术语都将至少出现一次,我们可以使用内部联接。在更一般的情况下,我们可能希望返回零计数,我们将使用外部联接

SELECT w.terms
     , COUNT(1) AS `COUNT`
  FROM ( SELECT t.terms
           FROM `table` t
          GROUP BY t.terms
       ) w
  JOIN `table` c
    ON c.terms LIKE CONCAT('%', w.terms ,'%')
 GROUP BY w.terms
 ORDER BY w.terms
在与
类似的比较中,百分号是与任何字符(零、一个或多个)匹配的通配符

如果
术语
可能包含下划线或百分比字符,我们可以对它们进行转义,这样它们就不会被类似的比较视为通配符。这样的表达式应该可以实现以下目的:

 REPLACE(REPLACE( w.terms ,'_','\_'),'%','\%')
所以我们会有这样一个查询:

SELECT w.terms
     , COUNT(1) AS `COUNT`
  FROM ( SELECT t.terms
           FROM `table` t
          GROUP BY t.terms
       ) w
  JOIN `table` c
    ON c.terms LIKE CONCAT('%',REPLACE(REPLACE( w.terms ,'_','\_'),'%','\%'),'%')
 GROUP BY w.terms
 ORDER BY w.terms

还有其他将返回指定结果的查询模式。这只是一种方法的演示


注意:在问题中的示例中,每个
术语
都是另一个
术语
的子字符串,子字符串匹配出现在术语的开头。此查询还将查找术语不在开头的匹配项

e、 g.
dartboard
将被视为与
art

可以修改查询以匹配仅出现在其他
术语
开头的
术语

跟进

对于示例数据,返回:

terms      COUNT     matched_terms
---------  --------  -------------------------
art               3  art,art deco,artistic
art deco          1  art deco
artistic          1  artistic
elephant          1  elephant
paint             3  paint,painting,paintings
painting          2  painting,paintings
paintings         1  paintings
除了
COUNT(1)
aggregate之外,我还在select列表中包含了另一个表达式。这不是必需的,但它确实提供了一些关于哪些术语被认为是匹配项的附加信息

 GROUP_CONCAT(DISTINCT c.terms ORDER BY c.terms) AS `matched_terms`
注意:如果
terms
可能包含反斜杠字符,我们也可以使用另一个替换来转义这些字符

 REPLACE(REPLACE(REPLACE( w.terms ,'\\','\\\\'),'_','\_'),'%','\%')
                 ^^^^^^^^         ^^^^^^^^^^^^^

请与我们分享您的试用。您的替换功能可自行替换每行的术语;请看我答案中的建议1和建议2。非常好的答案!但是你不需要一个w.term
分组吗?同样在
ORDER BY
之前?@MichaelK:是的。我们确实需要一个小组。啊!(答案经过编辑以包含更正。)难以置信的答案!非常感谢。这不仅实现了我的目标,而且在研究你的答案时我学到了很多。我在一个有26k行的表上运行了它,查询用了175s才完成。@OBreaux1:LIKE与百分比通配符的比较要求检查
表中的每一行,检查每个
术语
条目。如果表中的行较长(表中的列较多),则索引。。。在
表(术语)
上,如果完全通过索引满足查询,则可能会提高性能。@OBreaux1:此查询返回包含
术语的行数;如果存在匹配项,则计数将递增1。例如,“dartmart”将匹配“art”,但计数将增加1。不是两个,即使“艺术”出现了两次。