mysql语句性能优化-使用case when 代替count(*)


前言

负责运维的项目有个页面加载特别慢,打开差不多要2分钟,但是页面数据并不算多,只有几百条。为了把页面加载速度慢的问题解决,通过查看后台日志,发现有一条慢sql,里面写的内容又长又臭。


一、问题SQL

 SELECT
        cnooc.*
    t3.project_name as project_name,
        t3.`year` as year,
        t3.award_name as award_name,
        t3.award_id as award_id,
        t3.major_code as major_code,
        t3.major_value as major_value,
        t1.awardTypeValue as awardTypeValue,
        t1.application_level as application_level,
        t1.average_score as initial_evaluation_score,
        t1.final_evaluation_level as final_evaluation_level,
        t1.create_unit_value as create_unit_value,
        t1.id as id,
        (
        SELECT
        count(*)
        FROM
        yk_score
        WHERE
        istjjt = '1'
        AND
        project_name = t3.project_name
        AND
        status = 1
        AND
        judges_level = 1
        ) AS istjjt,
        ( ( SELECT count( * ) FROM yk_score WHERE final_evaluation_level = '特等奖' AND project_name = t3.project_name AND STATUS = 1 AND judges_level = 1 ) * 4 + ( SELECT count( * ) FROM yk_score WHERE final_evaluation_level = '一等奖' AND project_name = t3.project_name AND STATUS = 1 AND judges_level = 1 ) * 3+ ( SELECT count( * ) FROM yk_score WHERE final_evaluation_level = '二等奖' AND project_name = t3.project_name AND STATUS = 1 AND judges_level = 1 ) * 2 + ( SELECT count( * ) FROM yk_score WHERE final_evaluation_level = '三等奖' AND project_name = t3.project_name AND STATUS = 1 AND judges_level = 1 )
        ) / ( SELECT count( * ) FROM yk_score WHERE project_name = t3.project_name AND STATUS = 1 AND judges_level = 1 ) AS dpf,
        (
        SELECT
        count(*)
        FROM
        yk_score
        WHERE
        final_evaluation_level = '特等奖'
        AND
        project_name = t3.project_name
        AND
        status = 1
        AND
        judges_level = 1
        ) AS grand_prize,
        (
        SELECT
        count(*)
        FROM
        yk_score
        WHERE
        final_evaluation_level = '一等奖'
        AND
        project_name = t3.project_name
        AND
        status = 1
        AND
        judges_level = 1
        ) AS first_prize,
        (
        SELECT
        count(*)
        FROM
        yk_score
        WHERE
        final_evaluation_level = '二等奖'
        AND
        project_name = t3.project_name
        AND
        status = 1
        AND
        judges_level = 1
        ) AS second_prize,
        (
        SELECT
        count(*)
        FROM
        yk_score
        WHERE
        final_evaluation_level = '三等奖'
        AND
        project_name = t3.project_name
        AND
        status = 1
        AND
        judges_level = 1
        ) AS third_prize,
        (
        SELECT
        count(*)
        FROM
        yk_score
        WHERE
        final_evaluation_level = '不推荐'
        AND
        project_name = t3.project_name
        AND
        status = 1
        AND
        judges_level = 1
        ) AS no_prize,
        (
        SELECT
        count(*)
  yk_score
        WHERE
        project_name = t3.project_name
        AND
        status = 1
        AND
        judges_level = 1
        ) AS total_ticket,
        (
        select
        SUM(final_evaluation_score)/count(*)
        from
        yk_score
        where
        project_name = t3.project_name
        AND
        status = 1
        AND
        judges_level = 1
        ) as average_score
        FROM
        yk_score t3
        INNER JOIN
        yk_cnooc_progress t1
        ON
        t3.award_declaration_id = t1.id
        AND
        t1.review_link = 2
 ) as cnooc
 order by dpf desc,first_prize desc,second_prize desc,third_prize desc,initial_evaluation_score desc
    </select>

二、修改后SQL

代码如下(示例):

 SELECT
        cnooc.* ,
        (	grand_prize * 4 + first_prize * 3+ second_prize* 2 +third_prize ) / (grand_prize+first_prize+second_prize+third_prize+no_prize) AS dpf,
        (grand_prize+first_prize+second_prize+third_prize+no_prize) AS total_ticket
        FROM
        (
        SELECT
        t1.average_score AS initial_evaluation_score,
        t1.id AS id,
        t1.year AS year,
        ( SELECT count( * ) FROM yk_scorecur WHERE istjjt = '1' AND project_name = t3.project_name ) AS istjjt,
        count(case when(final_evaluation_level="特等奖") then 1 else null end)as grand_prize ,
        count(case when(final_evaluation_level="一等奖") then 1 else null end)as first_prize,
        count(case when(final_evaluation_level="二等奖") then 1 else null end)as second_prize,
        count(case when(final_evaluation_level="三等奖") then 1 else null end)as third_prize,
        count(case when(final_evaluation_level="不推荐") then 1 else null end)as no_prize
        FROM
        yk_scorecur t3
        INNER JOIN vw_cnooc_progresscur t1 ON t3.award_declaration_id = t1.id
        GROUP BY
        t3.project_name
        ) AS cnooc
        <include refid="common.search_template"></include>
        order by dpf desc,first_prize desc,second_prize desc,third_prize desc,initial_evaluation_score desc

总结

修改后,sql 由原来的2分钟,变成了0.3秒。对于sql语句,尽量少用多个select count(*) 的语句。如果能用count case went 可以大大加快速度。

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
MySQLCase When 语句可以实现多条件查询的功能,比如可以根据不同的条件对查询结果进行分类,根据分类结果对数据进行汇总、计数或统计等操作。 Case When 语句的基本语法如下: ``` select case [when condition1 then result1] [when condition2 then result2] [when condition3 then result3] ... [else default_result] end from table_name; ``` 其中,when 后的条件可以是表达式、逻辑运算符、比较运算符等,如果 condition1 结果为 true,就返回 result1,否则继续判断 condition2,以此类推。 比如,如果有这样一张用户表,其中包含了用户的姓名、性别、年龄、所在城市等信息: ``` CREATE TABLE users ( id INT NOT NULL AUTO_INCREMENT, name VARCHAR(50) NOT NULL, gender ENUM('male', 'female') NOT NULL, age INT NOT NULL, city VARCHAR(50) NOT NULL, PRIMARY KEY (id) ); INSERT INTO users (name, gender, age, city) VALUES ('Tom', 'male', 26, 'Beijing'), ('Lily', 'female', 23, 'Shanghai'), ('Mary', 'female', 32, 'Shenzhen'), ('Jack', 'male', 38, 'Guangzhou'), ('Lucy', 'female', 24, 'Hangzhou'), ('David', 'male', 29, 'Shanghai'), ('Emma', 'female', 27, 'Beijing'), ('Mike', 'male', 31, 'Guangzhou'), ('Ella', 'female', 28, 'Shenzhen'), ('John', 'male', 36, 'Hangzhou'); ``` 我们可以使用 Case When 语句对用户数据进行分类,比如按照性别进行分类: ``` SELECT gender, COUNT(*) AS count FROM users GROUP BY gender ORDER BY CASE WHEN gender='male' THEN 1 WHEN gender='female' THEN 2 ELSE 3 END; -- 输出结果如下: -- gender count -- male 4 -- female 6 ``` 这里用 Case When 语句对性别进行分类,count 统计每种分类的数量,同时使用 order by 指定分类的顺序。 除了精确匹配外,Case When 语句还可以使用 like 或 in 等条件表达式进行模糊匹配,比如按照年龄段进行分类: ``` SELECT CASE WHEN age < 20 THEN '少年' WHEN age BETWEEN 20 AND 30 THEN '青年' WHEN age BETWEEN 30 AND 40 THEN '中年' ELSE '老年' END AS age_group, COUNT(*) AS count FROM users GROUP BY age_group; -- 输出结果如下: -- age_group count -- 青年 4 -- 中年 3 -- 老年 3 ``` 这里将用户按照年龄段进行分类,count 统计每种分类的数量,同时使用 as 将分类结果命名为 age_group。 Case When 语句可以灵活地使用在各种查询场景中,比如我们可以根据不同的条件返回不同的文本、数值或日期格式,也可以从多个字段中派生出新的字段等。需要注意的是,Case When 语句也需要谨慎使用,因为过多的分支会降低查询性能,建议根据实际需求进行调整。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值