Mysql按条件求和Sum函数

首先在写这博客的初衷是因为在工作开发过程中遇到了数据汇总问题,并且有的还是按条件汇总,这就有点小麻烦,然而学会使用sum函数之后,这些问题就迎刃而解了。是不是很Nice。好记性不如烂笔头!再此,希望能帮到类似需求的小伙伴,谢谢!!!下面进入正题。

一、汇总数据展示:

二、后台数据封装类:

public class FtDailyStaticData {

    private int moduleTotal;//模块总数
    private int modulePass;//模块通过的数量
    private int caseTocal;//用例总数
    private int casePassed;//用例通过数
    private int lineCover;//代码通过行数
    private int lineTotal;//代码总行数
    private int funcCover;//函数通过数
    private int funcTocal;//函数总数
}
//set、get方法省略

三、sql语句编写:

<select id="findSum" parameterType="java.lang.Integer" resultType="java.util.Map">
        SELECT COUNT(1) AS moduleTocal,
        SUM(IF(result='true',1,0)) AS modulePass,
        <!--SUM(CASE WHEN result = 'true' THEN 1 ELSE 0 END) AS passtotal,-->
        SUM(total) AS caseTocal,
        SUM(passed) AS casePass,
        SUM(line_total) ,
        SUM(line_cover),
        SUM(func_cover),
        SUM(func_total)
        FROM ft_build_info WHERE build_id  = #{buildId}
    </select>

其中第三行和第四行的代码作用一样,只是两种不同的函数。这就是按条件汇总数据的函数:

        SUM(IF(result='true',1,0)) AS modulePass,
        SUM(CASE WHEN result = 'true' THEN 1 ELSE 0 END) AS passtotal, 

注意:sum()是一个函数,在取值的时候要用map取值。这两个函数挺重要的,建议理解掌握

四、数据访问层

public interface FtBuildInfoDao {

    //这里用arrayList接受,是用来保证查询的数据是升序还是降序处理的
    //ArrayList<Map<String,Object>> findSum(Integer buildId);

    Map<String,Object> findSum(Integer buildId);
}

 注意:用ArrayList接受Map做泛型的作用,如果没有要求对数据进行排序的要求,直接可以选择用Map进行接收!

五、业务层(取值):

public FtDailyStaticData findSum(Integer buildId) {
        //ArrayList<FtDailyStaticData> lists = new ArrayList<FtDailyStaticData>();
        //ArrayList<Map<String, Object>> list = ftTestDao.findSum(buildId);
       Map<String, Object> map = ftTestDao.findSum(buildId);
        FtDailyStaticData ftDailyStaticData = new FtDailyStaticData();
        //for (Map<String, Object> map : list) {
            Object object = map.get("moduleTocal");
            int moduleTocal = Integer.parseInt(object.toString());
            ftDailyStaticData.setModuleTotal(moduleTocal);//统计模块总数

            ftDailyStaticData.setModulePass(Integer.parseInt(map.get("modulePass").toString()));
            ftDailyStaticData.setCaseTocal(Integer.parseInt(map.get("caseTocal").toString()));
            ftDailyStaticData.setCasePassed(Integer.parseInt(map.get("casePass").toString()));
            ftDailyStaticData.setLineTotal(Integer.parseInt(map.get("SUM(line_total)").toString()));
            ftDailyStaticData.setLineCover(Integer.parseInt(map.get("SUM(line_cover)").toString()));
            ftDailyStaticData.setFuncTocal(Integer.parseInt(map.get("SUM(func_total)").toString()));
            ftDailyStaticData.setFuncCover(Integer.parseInt(map.get("SUM(func_cover)").toString()));
            //lists.add(ftDailyStaticData);
        //}
        return ftDailyStaticData;
    }
}

注意 :map取值的时候根据你sql查询的结果字段名进行取值,否则取不到相关的信息!!

六、控制层省略,直接调用业务层方法即可 

七、测试:

成功返回,nb。 

引申:

SELECT
t.*,
CONCAT (ROUND (IFNULL((t.Pass * 100 / t.Total), 0),2),'%') As Rate <!--求百分比并且保留两位小数-->
from
(
SELECT
COALESCE( SUM(total),0 ) As Total,  <!--这个意思是当total为null时返回0-->
COALESCE( SUM(passed),0 ) AS Pass,
COALESCE( SUM(error),0 ) AS Error
FROM ft_build_info fb
<where>
    <if test="project != null and project.size !=0">
        and fb.ft_project_name in
        <foreach collection="project" item="item" open="(" separator="," close=")">
            #{item}
        </foreach>
    </if>
    <if test="version != null and version.size !=0">
        and fb.ft_version in
        <foreach collection="version" item="item" open="(" separator="," close=")">
            #{item}
        </foreach>
    </if>
    <if test="moduleName != null and moduleName.size !=0">
        and fb.module_name in
        <foreach collection="moduleName" item="item" open="(" separator="," close=")">
            #{item}
        </foreach>
    </if>
    <if test="type != null and type.length !=0">
        and fb.flag in
        <foreach collection="type" item="item" open="(" separator="," close=")">
            #{item}
        </foreach>
    </if>
    <if test="beginTime != null and beginTime != ''">
        and <![CDATA[fb.begin_time >= #{beginTime}]]>
    </if>
    <if test="endTime != null and endTime != ''">
        and <![CDATA[fb.end_time <= #{endTime}]]>
    </if>
</where>
) t

字符串日期格式的比较大小:

SELECT 

FROM 
ft_build_info fb 
WHERE fb.begin_time >= CONCAT(DATE_FORMAT(DATE_ADD(NOW(),INTERVAL 0 DAY),'%Y-%m-%d'), ' 00:00:00') 
AND fb.end_time <= CONCAT(DATE_FORMAT(DATE_ADD(NOW(),INTERVAL 0 DAY),'%Y-%m-%d'),' 23:59:59')

其中DATE_ADD()函数是在该日期上加一个时间数,INTERVAL 后为正数就是加,为负数是减。

DATE_SUB()函数是在该日期上减去一个时间数,INTERVAL 后为负数就是加,为正数是减。

在做求和并且计算百分比的时候出现了一个问题,记录一下!! 

修改之前的sql:

SELECT
t.* ,
CONCAT (ROUND (IFNULL((t.LineCover * 100 / t.LineTotal), 0.00),2),'%' ) As LineRate
FROM
(
SELECT
COALESCE( SUM(fb.line_total),0 ) As LineTotal, 
COALESCE( SUM(fb.line_cover),0 ) AS LineCover,
CONCAT(fb.module_name,'') AS moduleName
FROM 
ft_build_info fb
WHERE  fb.flag = 1 GROUP BY fb.module_name 
) t
WHERE  1=1 ORDER BY LineRate desc LIMIT 10

结果如下:

很奇怪,我明明是按照LineRate降序排列 的,为什么第一条数据排在第一条,很明显不对的。这是因为我们在使用concat函数时拼接了一个‘%’,这样在后续使用ORDER BY LineRate的时候,就会以字符串形式进行排序,怎么解决呢?

方法如下 :

方法一:ORDER BY '123'+0;(首推)

方法二:ORDER BY '123'*1; 

方法三:ORDER BY CAST('123' AS SIGNED);
方法四:ORDER BY CONVERT('123',SIGNED);

注意:其中'123'是你要排序的字段。

演示第一种方法:

发布了23 篇原创文章 · 获赞 12 · 访问量 9546

猜你喜欢

转载自blog.csdn.net/geng2568/article/details/89329444
今日推荐