因为遇到这篇问题,为了解决问题而撰写此CountArrayDistinct方法。
关于本方法有任何更好的做法、可以提升效能或是任何建议,欢迎提出讨论~~
-- ========================-- CountArrayDistinct-- 建立方法,计算阵列文字(ex."a,b,c,b")中不重複的数量-- ArrStr VARCHAR(21845) 要进行处理的字串-- pos VARCHAR(10) 分割字串-- ===================DELIMITER $$DROP FUNCTION IF EXISTS CountArrayDistinct $$CREATE FUNCTION CountArrayDistinct(ArrStr VARCHAR(21845),pos VARCHAR(10)) RETURNS intBEGINSET @startIndex = 0;SET @posIndex = 0;set @result = 0;-- 如果已经有临时表了就不用重建CREATE TEMPORARY TABLE IF NOT EXISTS `tmp_CountArrayDistinct_table`( name VARCHAR(1000) NOT NULL);-- 清空临时表避免上一次的残留delete from tmp_CountArrayDistinct_table; SET @posIndex = LOCATE(pos,ArrStr);if @posIndex > 0 then -- 依序加分割的字串项目加入临时表(最后一个会被略过) while @posIndex > 0 do-- 加入insert into tmp_CountArrayDistinct_table values(SUBSTRING(ArrStr,@startIndex+1,@posIndex-@startIndex-1));-- 处理下一个起始索引set @startIndex = @posIndex;-- 找下一个SET @posIndex = LOCATE(pos,ArrStr,@startIndex+1); end while; -- 将最后一个字串项目加入临时表 insert into tmp_CountArrayDistinct_table values(SUBSTRING_INDEX(ArrStr,pos,-1)); -- 输出不重複数量 set @result = (select count(DISTINCT name ) from tmp_CountArrayDistinct_table where name!='' and name is not null);ELSEIf LENGTH(ArrStr)>0 THEN -- 有传入文字,但没找到分割字元set @result = 1;else set @result = 0;END IF;RETURN @result;END $$DELIMITER ;
感恩ckp6250大大提供优化版本
SELECTcount(1) FROM(SELECT@num := @num + 1,SUBSTRING_INDEX( SUBSTRING_INDEX( 'a,b,c,b,a,z', ',', @num ), ',',- 1 ) AS str FROMinformation_schema.GLOBAL_STATUS a,( SELECT @num := 0 ) b WHERE@num < CHAR_LENGTH( 'a,b,c,b,a,z' )- CHAR_LENGTH(REPLACE ( 'a,b,c,b,a,z', ',', '' ))+ 1GROUP BY str ) a
使用範例
select CountArrayDistinct( 'a,b,c,b,a,z' , ',' );-- 输出 4