Mysql 计算字符串中的唯一字符数

Mysql 计算字符串中的唯一字符数,mysql,sql,database,Mysql,Sql,Database,我正在寻找一个sql语句来计算字符串中唯一字符的数量 e、 g 我用REGEX和mysql字符串函数做了一些测试,但没有找到解决方案。没有直接或简单的方法。您可能需要编写一个存储函数来完成这项工作,并查看数据中可能需要的所有字符。下面是一个仅数字的示例,它可以扩展为存储函数中的所有字符 mysql> select * from test ; +------------+ | val | +------------+ | 11111111 | | 111222222 |

我正在寻找一个sql语句来计算字符串中唯一字符的数量

e、 g


我用REGEX和mysql字符串函数做了一些测试,但没有找到解决方案。

没有直接或简单的方法。您可能需要编写一个存储函数来完成这项工作,并查看数据中可能需要的所有字符。下面是一个仅数字的示例,它可以扩展为存储函数中的所有字符

mysql> select * from test ;
+------------+
| val        |
+------------+
| 11111111   |
| 111222222  |
| 1113333222 |
+------------+


select 
val, 
sum(case when locate('1',val) > 0 then 1 else 0 end ) 
+ sum( case when locate('2',val) > 0 then 1 else 0 end)
+ sum(case when locate('3',val) > 0 then 1 else 0 end)
+sum(case when locate('4',val) > 0 then 1 else 0 end ) as occurence
from test group by val


+------------+-----------+
| val        | occurence |
+------------+-----------+
| 11111111   |         1 |
| 111222222  |         2 |
| 1113333222 |         3 |
+------------+-----------+
或者,如果您有足够的时间,创建一个包含所有可以想到的字符的查找表。并在两行中进行查询

mysql> select * from test ;
+------------+
| val        |
+------------+
| 11111111   |
| 111222222  |
| 1113333222 |
+------------+
3 rows in set (0.00 sec)

mysql> select * from look_up ;
+------+------+
| id   | val  |
+------+------+
|    1 | 1    |
|    2 | 2    |
|    3 | 3    |
|    4 | 4    |
+------+------+
4 rows in set (0.00 sec)

select 
t1.val, 
sum(case when locate(t2.val,t1.val) > 0 then 1 else 0 end ) as occ 
from test t1,(select * from look_up)t2 
group by t1.val ;

+------------+------+
| val        | occ  |
+------------+------+
| 11111111   |    1 |
| 111222222  |    2 |
| 1113333222 |    3 |
+------------+------+

我认为这不是Mysql的工作, 但如果你足够努力,你可以做任何事;)

我不喜欢这个答案,但它是有效的,如果你只有数字,也不会太难看

SELECT 
    CASE WHEN yourcolumn LIKE '%1%' THEN 1 ELSE 0 END + 
    CASE WHEN yourcolumn LIKE '%2%' THEN 1 ELSE 0 END +
    CASE WHEN yourcolumn LIKE '%3%' THEN 1 ELSE 0 END + 
    CASE WHEN yourcolumn LIKE '%4%' THEN 1 ELSE 0 END +
    CASE WHEN yourcolumn LIKE '%5%' THEN 1 ELSE 0 END +
    CASE WHEN yourcolumn LIKE '%6%' THEN 1 ELSE 0 END +
    CASE WHEN yourcolumn LIKE '%7%' THEN 1 ELSE 0 END +
    CASE WHEN yourcolumn LIKE '%8%' THEN 1 ELSE 0 END +
    CASE WHEN yourcolumn LIKE '%9%' THEN 1 ELSE 0 END +
    CASE WHEN yourcolumn LIKE '%0%' THEN 1 ELSE 0 END
FROM yourtable

您可以做的一件事是创建一个包含所有字符的表,例如:

mysql> select * from chars;
+----+------+
| id | c    |
+----+------+
|  1 | 1    |
|  2 | 2    |
|  3 | 3    |
|  4 | 4    |
+----+------+
如果您的词表如下所示:

mysql> select * from words;
+----+-----------+
| id | word      |
+----+-----------+
|  1 | 111222333 |
|  2 | 11111111  |
|  3 | 2222111   |
|  4 | 5555555   |
+----+-----------+
mysql> select word, count(c) from words w inner join chars c on locate(c.c, word) group by word;
+-----------+----------+
| word      | count(c) |
+-----------+----------+
| 11111111  |        1 |
| 111222333 |        3 |
| 2222111   |        2 |
+-----------+----------+
然后,您可以在字符位于单词中的条件下连接这些表,并获得计数,如下所示:

mysql> select * from words;
+----+-----------+
| id | word      |
+----+-----------+
|  1 | 111222333 |
|  2 | 11111111  |
|  3 | 2222111   |
|  4 | 5555555   |
+----+-----------+
mysql> select word, count(c) from words w inner join chars c on locate(c.c, word) group by word;
+-----------+----------+
| word      | count(c) |
+-----------+----------+
| 11111111  |        1 |
| 111222333 |        3 |
| 2222111   |        2 |
+-----------+----------+
DROP函数(如果存在)test.count\u chrs;
CREATE DEFINER=`test`@`localhost`函数`count\u chrs`(s CHAR(100))返回CHAR(4)
开始
声明字符串长度int(4);
声明唯一的字符串字符(100)默认为“”;
声明count_unique int(4)默认为0;
声明当前字符int(4)默认为1;
设置字符串长度=字符长度;
而当前的_char这是为了好玩,对吗

SQL就是处理一组行,所以如果我们可以将一个“单词”转换成一组字符作为行,那么我们就可以使用“group”函数来做有用的事情

使用“关系数据库引擎”进行简单的字符操作感觉是错误的。不过,是否可以仅使用SQL来回答您的问题?是的,是

现在,我总是有一个表,它有一个整数列,其中大约有500行,升序为1。。500它被称为“整数系列”。这是一个非常小的表,使用了很多,所以它被缓存在内存中。它设计用于替换“选择1…”中的
。。。联合…
查询中的文本

交叉连接
(也包括任何
内部连接
)中使用整数,可以根据整数生成任何可计算的连续行(表)。我使用它来生成一年中的天数,解析逗号分隔的字符串等

现在,可以使用sql
mid
函数返回给定位置的字符。通过使用“integerseries”表,我可以“轻松地”将“word”转换为每个字符一行的字符表。然后使用“组”功能

SET @word='Hello World';

SELECT charAtIdx, COUNT(charAtIdx)
FROM (SELECT charIdx.id,
    MID(@word, charIdx.id, 1) AS charAtIdx 
    FROM integerseries AS charIdx
    WHERE charIdx.id <= LENGTH(@word)
    ORDER BY charIdx.id ASC
    ) wordLetters
GROUP BY
   wordLetters.charAtIdx
ORDER BY charAtIdx ASC  
注意:输出中的行数是字符串中不同字符的数目。因此,如果对输出行的数量进行计数,则“不同字母”的数量将是已知的

此观察结果将用于最终查询

最后一个问题是:

这里有趣的一点是将“integerseries”“cross-join”限制(1..length(word))移到实际的“join”中,而不是在
where
子句中进行。这为优化器提供了有关如何限制执行
连接时生成的数据的线索

SELECT 
   wordLetterCounts.wordId,
   wordLetterCounts.word,   
   COUNT(wordLetterCounts.wordId) AS letterCount
FROM 
     (SELECT words.id AS wordId,
             words.word AS word,
             iseq.id AS charPos,
             MID(words.word, iseq.id, 1) AS charAtPos,
             COUNT(MID(words.word, iseq.id, 1)) AS charAtPosCount
     FROM
          words
          JOIN integerseries AS iseq
               ON iseq.id BETWEEN 1 AND words.wordlen 
      GROUP BY
            words.id,
            MID(words.word, iseq.id, 1)
      ) AS wordLetterCounts
GROUP BY
   wordLetterCounts.wordId  
输出:

charAtIdx  count(charAtIdx)  
---------  ------------------
                            1
d                           1
e                           1
H                           1
l                           3
o                           2
r                           1
W                           1
wordId  word                  letterCount  
------  --------------------  -------------
     1  3333333333                        1
     2  1113333333                        2
     3  1112222444                        3
     4  Hello World                       8
     5  funny - not so much?             13
Word表格和数据:

CREATE TABLE `words` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `word` varchar(128) COLLATE utf8mb4_unicode_ci NOT NULL,
  `wordlen` int(11) NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=6 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;

/*Data for the table `words` */

insert  into `words`(`id`,`word`,`wordlen`) values (1,'3333333333',10);
insert  into `words`(`id`,`word`,`wordlen`) values (2,'1113333333',10);
insert  into `words`(`id`,`word`,`wordlen`) values (3,'1112222444',10);
insert  into `words`(`id`,`word`,`wordlen`) values (4,'Hello World',11);
insert  into `words`(`id`,`word`,`wordlen`) values (5,'funny - not so much?',20);
Integerseries表:范围1。。这个例子是30

CREATE TABLE `integerseries` (
  `id` int(11) unsigned NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=500 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci

有几个级别的子查询可能会延迟一些时间,并且需要对具有较长字符串的列进行扩展,但是通过使用UNPIVOT将其转到另一侧,它非常简单

declare @Data table (RowID nvarchar(1), StringData nvarchar(10))
insert into @Data values (N'1', N'3333333333'),(N'2', N'1113333333'),(N'3', N'1112222444')

select  t1.StringData, cast(t2.CharCount as nvarchar) as 'Unique Characters in String'
from    @Data t1
        inner join (
            select  RowID,count(*) as 'CharCount'
            from    (
                    select  distinct RowID, [char]
                    from    (
                        select  RowID,
                            substring(StringData,1,1) as '1',
                            substring(StringData,2,1) as '2',
                            substring(StringData,3,1) as '3',
                            substring(StringData,4,1) as '4',
                            substring(StringData,5,1) as '5',
                            substring(StringData,6,1) as '6',
                            substring(StringData,7,1) as '7',
                            substring(StringData,8,1) as '8',
                            substring(StringData,9,1) as '9',
                            substring(StringData,10,1) as '10'
                        from    @Data
                        ) Unpivd
                    unpivot ( [char] for chars in ([1],[2],[3],[4],[5],[6],[7],[8],[9],[10])) unpiv
                    where [char] <> ''
                ) CharCounter
            group by RowID
            ) t2
            on t2.RowID = t1.RowID

你真的认为这是MySQL的工作吗?也许这篇文章可以帮你解决这个问题。[1] 您需要编写代码块来完成此操作,请给我一些时间,我会这样做。硬编码查询太多了!如果字符串中有
[A-Z]
[A-Z]
[@#$%^]
等,该怎么办?@Vikrant那么您认为在mysql中完成任务最简单的方法是什么,作为答案发布。这不是解决方案。我们需要编写代码块来获得这个结果。您的解决方案无效,需要硬代码。@Anvesh正如我在回答中提到的,mysql中没有可用的此类函数来完成这些工作,但是如果您仍然想在mysql中完成这些工作,这里有一种方法。如果你知道更好的方法,就加上这个。请注意,更好的方法不是使用PHP或其他一些语言(我可以给出100个示例),而是使用mysql。我甚至不知道你们为什么在这里批评Abhik为OP给出的精确输入参数提供了解决方案。MySQL不是这项工作的工具,甚至没有讨论过。这是一种方法。你的存储过程被破坏了,所以不要试图贬低其他有效的答案。我不介意测试它,但这看起来是正确的。我要说的唯一一件事是func返回的是一个整数,而不是定义中所述的字符,这是一个MySQL问题,而不是我的示例中的TSQL。
StringData  Unique Characters in String
3333333333  1
1113333333  2
1112222444  3