MySQL利用count()函数统计总数的技巧

MySQL利用count()函数统计总数的技巧,第1张

2020-03-01

对于count的函数的使用,我们常见的一个错误是在括号内随意指定一个列去统计结果集的行数。但只有指定的行确实都是有值的时候,统计的才是实际的行数,否则可能统计的结果并不是实际的行数。而对于MyISAM存储引擎,如果某一列的值确实不可能为null时,MySQL内部就会将count()函数优化成count(*),若没有带where条件,此时计算速度是非常快的,因为此时没有实际的去计算表的行数。

总结: 对于MyISAM存储引擎,不带where条件的count(*)是非常快的。

技巧:

利用上述MyISAM的count(* )特性,加速一些特定查询条件的count()查询。

如:

对于select count(* ) from tablename where id >10可以做如下的反转查询:

select (select count(* ) from tablename) - count(* ) from tablename where id <10

因为这样在查询阶段MySQL将子查询当做一个常数来处理,大大减少了扫描的行数。

以时间为跨度统计不同的值,在该时间出现的次数。

语言如下:

select count(*),'列名' from tablename group by '列名'

select count(*),a_yqm from user group by a_yqm

举例:

这里,我要查询出1年内每个月份periods字段不同值的次数。

比如下图中可见的2015-4月,periods为2出现了3次,3出现了1次,最关键的是 periods你不知道有多少种可能的值,也许这个月有1,也许没有。

CREATE TABLE person (

    name  varchar(20)

)

INSERT INTO person VALUES ('a,b,c')

INSERT INTO person VALUES ('a,b')

INSERT INTO person VALUES ('a,c')

DELIMITER //

DROP FUNCTION GetTextCount //

/**********

-- 获取字符串中有几个部分.

**********/

CREATE FUNCTION GetTextCount(pSourceText  VARCHAR(255),  pDivChar  CHAR(1))

RETURNS TINYINT

BEGIN

-- 预期结果. 

DECLARE vResult TINYINT

-- 当前逗号位置.

DECLARE vIndex INT

-- 前一个逗号的位置.

DECLARE vPrevIndex INT

-- 结果的初始值.

SET vResult = 1

-- 查询第一个 逗号的位置.

SET vIndex = INSTR(pSourceText, pDivChar)

IF vIndex = 0 THEN

-- 参数中没有逗号,直接返回.

RETURN vResult

END IF

-- 初始化情况,前一个逗号不存在.

SET vPrevIndex = 0

-- 循环处理。

WHILE vIndex > 0 DO

-- 结果递增.

SET vResult = vResult + 1

-- 前一个逗号的位置 = 当前逗号的位置

SET vPrevIndex = vIndex

-- 查询下一个逗号的位置.

SET vIndex = LOCATE(pDivChar,  pSourceText,  vPrevIndex + 1)

END WHILE

-- 返回结果.

RETURN vResult

END

//

DROP FUNCTION GetTextValue //

/**********

-- 获取字符串中具体某一个部分的数据.

**********/

CREATE FUNCTION GetTextValue(pSourceText  VARCHAR(255),  pDivChar  CHAR(1), pIndex  TINYINT)

RETURNS VARCHAR(255) 

BEGIN

-- 预期结果. 

DECLARE vResult VARCHAR(255)

IF pIndex = 1 THEN

SELECT SUBSTRING_INDEX(pSourceText,  pDivChar,  1)  INTO  vResult

ELSE

SELECT 

REPLACE(

SUBSTRING_INDEX(pSourceText,  pDivChar,  pIndex),

CONCAT(SUBSTRING_INDEX(pSourceText,  pDivChar,  pIndex - 1) , pDivChar),

'') INTO  vResult

END IF

-- 返回.

RETURN vResult

END

//

DELIMITER 

SELECT

GetTextValue(t.name, ',', MaxNum.No) AS `名称`,

    COUNT(*) AS `个数`

FROM

person t,

(SELECT 1 No UNION ALL

 SELECT 2 No UNION ALL

 SELECT 3 No UNION ALL

 SELECT 4 No UNION ALL

 SELECT 5 No ) MaxNum

WHERE

GetTextCount(t.name, ',') >= MaxNum.No

GROUP BY

    GetTextValue(t.name, ',', MaxNum.No)

+------+------+

| 名称 | 个数 |

+------+------+

| a    |    3 |

| b    |    2 |

| c    |    2 |

+------+------+

3 rows in set (0.01 sec)


欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/zaji/6158113.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2023-03-16
下一篇 2023-03-16

发表评论

登录后才能评论

评论列表(0条)

保存