优化这段sql SELECT (CASE WHEN DATE_FORMAT( `start_time`, '%H:%i:%S' ) > '00:00:00' and DATE_FORMAT( `start_time`, '%H:%i:%S' ) <= '03:59:59' THEN '00:00-03:59' WHEN DATE_FORMAT( `start_time`, '%H:%i:%S' ) > '04:00:00' and DATE_FORMAT( `start_time`, '%H:%i:%S' ) <= '07:59:59' THEN '04:00-07:59' WHEN DATE_FORMAT( `start_time`, '%H:%i:%S' ) > '08:00:00' and DATE_FORMAT( `start_time`, '%H:%i:%S' ) <= '11:59:59' THEN '08:00-11:59' WHEN DATE_FORMAT( `start_time`, '%H:%i:%S' ) > '12:00:00' and DATE_FORMAT( `start_time`, '%H:%i:%S' ) <= '15:59:59' THEN '12:00-15:59' WHEN DATE_FORMAT( `start_time`, '%H:%i:%S' ) > '16:00:00' and DATE_FORMAT( `start_time`, '%H:%i:%S' ) <= '19:59:59' THEN '16:00-19:59' WHEN DATE_FORMAT( `start_time`, '%H:%i:%S' ) > '20:00:00' and DATE_FORMAT( `start_time`, '%H:%i:%S' ) <= '23:59:59' THEN '20:00-23:59' ELSE '' END) AS timeInterval, IFNULL( SUM( `dual_time` ), 0 ) AS totalTime, IFNULL( COUNT(1), 0 ) AS totalCall, IFNULL( SUM( CASE WHEN `local_action` = '主叫' THEN 1 ELSE 0 END ), 0 ) AS active, IFNULL( SUM( CASE WHEN `local_action` = '被叫' THEN 1 ELSE 0 END ), 0 ) AS passive FROM `dwd_t_call_record` WHERE `person_no` = '653129200105072624' GROUP BY HOUR ( `start_time` ) DIV 4
时间: 2024-02-21 10:59:14 浏览: 170
可以使用 MySQL 的 `CASE WHEN` 语句来简化这段 SQL 语句,同时避免重复的日期格式化操作。简化后的 SQL 语句如下:
```
SELECT
CONCAT(HOUR(`start_time`) DIV 4 * 4, ':00-', HOUR(`start_time`) DIV 4 * 4 + 3, ':59') AS timeInterval,
IFNULL(SUM(`dual_time`), 0) AS totalTime,
IFNULL(COUNT(1), 0) AS totalCall,
IFNULL(SUM(`local_action` = '主叫'), 0) AS active,
IFNULL(SUM(`local_action` = '被叫'), 0) AS passive
FROM
`dwd_t_call_record`
WHERE
`person_no` = '653129200105072624'
GROUP BY
HOUR(`start_time`) DIV 4
```
这个 SQL 语句使用了 `CONCAT` 函数来生成时间区间,使用了 `SUM` 函数的布尔表达式参数来计算主叫和被叫的数量。同时,将日期格式化操作转化为了整数运算,避免了多次重复的格式化操作。
相关问题
优化这段sql SELECT (CASE WHEN DATE_FORMAT( start_time, '%H:%i:%S' ) > '00:00:00' AND DATE_FORMAT( start_time, '%H:%i:%S' ) <= '00:59:59' THEN '00:00-00:59' WHEN DATE_FORMAT( start_time, '%H:%i:%S' ) > '01:00:00' AND DATE_FORMAT( start_time, '%H:%i:%S' ) <= '0
这段 SQL 可以优化的地方有很多,以下是一些建议:
1. 使用 BETWEEN 代替多个 AND 进行时间区间比较,可以让代码更简洁易读。
2. 避免在 WHERE 子句中使用函数,可以提高查询效率。在这里,可以先将时间戳转换为时间格式,再进行比较。
3. 考虑使用索引来优化查询效率,可以根据具体情况选择对哪些列创建索引。
综上,可以将原来的 SQL 改写为:
```
SELECT
(CASE
WHEN TIME(start_time) BETWEEN '00:00:00' AND '00:59:59' THEN '00:00-00:59'
WHEN TIME(start_time) BETWEEN '01:00:00' AND '01:59:59' THEN '01:00-01:59'
-- 其他时间区间的判断
END) AS time_range,
COUNT(*) AS count
FROM
your_table
GROUP BY
time_range;
```
注意,这里假设 `start_time` 是一个时间戳类型的字段。如果不是,需要先将其转换为时间格式。另外,这里只是给出了一个示例 SQL,具体的优化方式需要根据实际情况进行调整。
select u_i.uid as uid, count(distinct act_month) as act_month_total, count(distinct case when year(act_time) = 2021 then act_day end) as act_days_2021, count(distinct case when year(act_time) = 2021 and tag = 'exam' then act_day end) as act_days_2021_exam, count(distinct case when year(act_time) = 2021 and tag = 'question' then act_day end) as act_days_2021_question from user_info u_i left join (select uid, start_time as act_time, date_format(start_time, '%Y%m') as act_month, date_format(start_time, '%Y%m%d') as act_day, 'exam' as tag from exam_record union all select uid, submit_time as act_time, date_format(submit_time, '%Y%m') as act_month, date_format(submit_time, '%Y%m%d') as act_day, 'question' as tag from practice_record ) exam_and_practice on exam_and_practice.uid = u_i.uid where u_i.level >= 6 group by uid order by act_month_total desc, act_days_2021 desc; 请用oracle语法来改写这段sql
以下是使用 Oracle 语法改写后的 SQL 查询语句:
```
SELECT u_i.uid,
COUNT(DISTINCT act_month) AS act_month_total,
COUNT(DISTINCT CASE
WHEN EXTRACT(YEAR FROM act_time) = 2021 THEN act_day
END) AS act_days_2021,
COUNT(DISTINCT CASE
WHEN EXTRACT(YEAR FROM act_time) = 2021 AND tag = 'exam' THEN act_day
END) AS act_days_2021_exam,
COUNT(DISTINCT CASE
WHEN EXTRACT(YEAR FROM act_time) = 2021 AND tag = 'question' THEN act_day
END) AS act_days_2021_question
FROM user_info u_i
LEFT JOIN (SELECT uid,
start_time AS act_time,
TO_CHAR(start_time, 'YYYYMM') AS act_month,
TO_CHAR(start_time, 'YYYYMMDD') AS act_day,
'exam' AS tag
FROM exam_record
UNION ALL
SELECT uid,
submit_time AS act_time,
TO_CHAR(submit_time, 'YYYYMM') AS act_month,
TO_CHAR(submit_time, 'YYYYMMDD') AS act_day,
'question' AS tag
FROM practice_record) exam_and_practice
ON exam_and_practice.uid = u_i.uid
WHERE u_i.level >= 6
GROUP BY u_i.uid
ORDER BY act_month_total DESC, act_days_2021 DESC;
```
在 Oracle 中,日期时间的函数使用 `EXTRACT`,日期格式化使用 `TO_CHAR`。同时,Oracle 中使用分号作为语句结束符。
阅读全文