查询扬子江地点的2024年第一季度的清障数据统计——SQL语句分析学习
1.查询扬子江地点的2024年第一季度的清障数据统计——SQL语句分析学习

实际在业务场景中使用到的的sql语句如下:
SELECT DISTINCT
t.f_eventid AS '事件ID',
DATE ( t.f_createtime ) AS '日期',-- t.f_eventid AS '事件ID'
CONCAT( t.f_vc_roadid, ' ', t.f_vc_roadname ) AS '清障位置',
CONCAT( 'K', t.f_str_position, '+', t.f_str_mileage ) AS '发现地点',
CASE
WHEN tc.f_category = 1 THEN
'轿车'
WHEN tc.f_category = 2 THEN
'客车'
WHEN tc.f_category = 3 THEN
'货车'
WHEN tc.f_category = 4 THEN
'危化品车' ELSE '未识别'
END AS '故障车型',
t.f_createtime AS '发现时间',
t.f_event_chuli_date AS '通知时间',
tr.F_RESCUE_DAODA_DATE AS '到达时间',
tr.F_RESCUE_LICHANG_DATE AS '撤离时间',
t.f_dt_endtime AS '结束时间',
TIMESTAMPDIFF( MINUTE, t.f_createtime, t.f_dt_endtime ) AS '处置时长(分钟)',
'故障救援' AS '救援类型',
t.f_vc_createname AS '填报人员'
FROM
KG_ZZDH.t_event t
RIGHT JOIN KG_ZZDH.t_event_rescue tr ON t.F_EVENTID = tr.F_EVENTID
RIGHT JOIN KG_ZZDH.t_event_car tc ON t.F_EVENTID = tc.F_EVENTID
WHERE
t.f_unitid = 'ff80818159af9032015a12539f900010' -- "扬子江单位id"
AND YEAR ( t.f_createtime ) = 2024
AND MONTH ( t.f_createtime ) IN ( 1, 2, 3 )
AND t.f_createtime IS NOT NULL
AND t.f_event_chuli_date IS NOT NULL
AND tr.F_RESCUE_DAODA_DATE IS NOT NULL
AND tr.F_RESCUE_LICHANG_DATE IS NOT NULL
AND t.f_dt_endtime IS NOT NULL
ORDER BY
t.f_createtime DESC;
2.SQL语句编写分解解释:
2.1 表的别名命名:
KG_ZZDH.t_event t
2.2 CASE语句映射:
某个表的字段f_category的值的情况分别有1,2,3,4以及空,并且想要把每个数字分别映射到轿车、客车、货车和危化品车,并且想要把这列表头设置为“故障车型”,可以使用case开头,end结尾的句型,并且使用when设置原来表中的情况,然后使用then来表示想要替换的名称,例如把数字1映射为轿车,使用如下:
CASE
WHEN tc.f_category = 1 THEN
'轿车'
WHEN tc.f_category = 2 THEN
'客车'
WHEN tc.f_category = 3 THEN
'货车'
WHEN tc.f_category = 4 THEN
'危化品车' ELSE '未识别'
END AS '故障车型',
2.3 TimeStampdiff函数计算时间相差值
TIMESTAMPDIFF可以计算两个日期中间相差多少秒,多少分钟或者多少小时等,使用方法如下:
TIMESTAMPDIFF( MINUTE, t.f_createtime, t.f_dt_endtime ) AS '处置时长(分钟)',
SQL语句中的TIMESTAMPDIFF函数是用于计算两个时间戳之间的差异的函数。这个函数在不同的数据库系统(如MySQL)中可能有不同的实现,但基本功能是相似的。TIMESTAMPDIFF函数的基本语法如下:
TIMESTAMPDIFF(unit, timestamp1, timestamp2)
unit是一个字符串,指定了你要计算的时间差单位,比如SECOND、MINUTE、HOUR、DAY、WEEK、MONTH、QUARTER或YEAR。timestamp1和timestamp2是两个时间戳,你可以指定它们的来源字段或者直接使用日期时间字符串。
在你提供的SQL语句中:
TIMESTAMPDIFF( MINUTE, t.f_createtime, t.f_dt_endtime ) AS '处置时长(分钟)',
t.f_createtime和t.f_dt_endtime是表t中的两个字段,分别代表某个事件的开始时间和结束时间。MINUTE是指定计算的时间单位为分钟。TIMESTAMPDIFF函数计算f_createtime和f_dt_endtime之间的分钟差,并将这个差值作为'处置时长(分钟)'这一列显示在查询结果中。
例如,如果t.f_createtime是一个时间戳 '2023-01-01 10:00:00',而t.f_dt_endtime是 '2023-01-01 10:30:00',那么TIMESTAMPDIFF函数将返回30,表示从开始时间到结束时间总共过去了30分钟。
这个函数对于需要计算时间长度、持续时间的数据库查询非常有用,比如在项目管理、活动策划或者任何需要跟踪时间跨度的情况中。
2.4 SQL语句右连接保证右边表格所有数据存在:
FROM
KG_ZZDH.t_event t
RIGHT JOIN KG_ZZDH.t_event_rescue tr ON t.F_EVENTID = tr.F_EVENTID
RIGHT JOIN KG_ZZDH.t_event_car tc ON t.F_EVENTID = tc.F_EVENTID
在这条SQL语句中,使用了两个RIGHT JOIN操作来连接三个不同的表。这些表可能是数据库中与事件、救援和车辆相关的表。下面是对每个部分的详细解释:
FROM KG_ZZDH.t_event t:
FROM关键字是SQL查询中用来指定要查询的表的部分。KG_ZZDH.t_event是数据库中一个名为t_event的表的完全限定名,其中KG_ZZDH是模式名(schema name),t_event是表名。t是一个别名,用来代表t_event表在查询中的简写方式。使用别名可以让SQL语句更简洁,尤其是在复杂的查询中。
RIGHT JOIN KG_ZZDH.t_event_rescue tr ON t.F_EVENTID = tr.F_EVENTID:
RIGHT JOIN是一种连接操作,它返回右 表(KG_ZZDH.t_event_rescue)的所有行,即使在左表(KG_ZZDH.t_event)中没有匹配的行。如果左表中有匹配的行,则结果集中也会包含左表的行。KG_ZZDH.t_event_rescue是另一个表的完全限定名,这里假设它包含了与事件相关的救援信息。tr是KG_ZZDH.t_event_rescue表的别名,用于在查询中简写。ON t.F_EVENTID = tr.F_EVENTID是连接条件,它指定了两个表之间的连接是通过它们共有的F_EVENTID字段来完成的。这意味着每个事件的F_EVENTID在t_event表和t_event_rescue表中是相同的。
RIGHT JOIN KG_ZZDH.t_event_car tc ON t.F_EVENTID = tc.F_EVENTID:
- 这是第二个
RIGHT JOIN操作,它将t_event表与t_event_car表连接起来。 KG_ZZDH.t_event_car是包含与事件相关的车辆信息的表的完全限定名。tc是t_event_car表的别名。ON t.F_EVENTID = tc.F_EVENTID是连接条件,与上面的RIGHT JOIN类似,它指定了t_event表和t_event_car表之间的连接是通过它们共有的F_EVENTID字段来完成的。
综上所述,这个SQL语句使用了两次RIGHT JOIN来将t_event表与t_event_rescue表和t_event_car表连接起来,以便能够从这三个表中检索相关的信息。每个RIGHT JOIN都是基于F_EVENTID字段的值来匹配记录的。这意味着最终的查询结果将包括t_event表中的所有记录,以及t_event_rescue和t_event_car表中与t_event表匹配的记录。如果没有匹配的记录,则t_event_rescue和t_event_car表的相关部分将为NULL。
2.5 Where条件筛选:
WHERE
t.f_unitid = 'ff80818159af9032015a12539f900010' -- "扬子江单位id"
AND YEAR ( t.f_createtime ) = 2024
AND MONTH ( t.f_createtime ) IN ( 1, 2, 3 )
AND t.f_createtime IS NOT NULL
AND t.f_event_chuli_date IS NOT NULL
AND tr.F_RESCUE_DAODA_DATE IS NOT NULL
AND tr.F_RESCUE_LICHANG_DATE IS NOT NULL
AND t.f_dt_endtime IS NOT NULL
因为我们需要筛选:f_createtime字段为2024年的数据,因此使用year函数,参数为t表的f_createtime字段,值必须等于2024,因此语句写为:YEAR ( t.f_createtime ) = 2024;
又因为需要筛选为第一季度的数据,因此我们需要包含1,2,3月份的数据,注意此处使用in关键词表示包含,而不是像筛选年度那样条件是等于,因此语句写为:MONTH ( t.f_createtime ) IN ( 1, 2, 3 )。
使用NOT NULL 关键词筛选此值必须有实际的值,不能包含null和空。
AND t.f_createtime IS NOT NULL
AND t.f_event_chuli_date IS NOT NULL
AND tr.F_RESCUE_DAODA_DATE IS NOT NULL
AND tr.F_RESCUE_LICHANG_DATE IS NOT NULL
AND t.f_dt_endtime IS NOT NULL
2.6 group by 与 distinct 去重的区别
GROUP BY 和 DISTINCT 都可以用来去除查询结果中的重复行,但它们的应用场景和功能有所不同。DISTINCT 关键字用于去除查询结果中的重复行,它作用于所有列。当我们只关心结果集中不同的行时,可以使用 DISTINCT。例如,如果您想从某个表中查询所有不同的城市,可以使用如下查询:
SELECT DISTINCT city FROM table_name;
这个查询将返回所有不同的城市,不包含重复的城市名。GROUP BY 子句用于将查询结果集中的多行数据根据一个或多个列进行分组,通常与聚合函数(如 COUNT(), SUM(), AVG(), MAX(), MIN() 等)一起使用,以便对每个分组的数据进行汇总。GROUP BY 可以用于更复杂的数据处理,比如您不仅想要去除重复行,还想要对每个独特的分组进行统计或计算。例如,如果您想查询每个城市的不同职位数量,可以使用如下查询:
SELECT city, COUNT(DISTINCT position) FROM table_name GROUP BY city;
这个查询将返回每个城市及其不同的职位数量。
总结一下区别:
DISTINCT用于去除查询结果中的完全重复的行。GROUP BY用于分组数据,并且通常与聚合函数一起使用,用于对每个分组的数据进行汇总。GROUP BY可以用于更复杂的数据分析,而DISTINCT通常用于简单的去重操作。GROUP BY可以与HAVING子句一起使用,以过滤分组后的结果,而DISTINCT不能与HAVING子句直接配合使用。
2.7 group by 与 having 如何联合使用
GROUP BY 和 HAVING 子句通常一起使用,以便对分组后的数据进行条件过滤。下面是它们的基本用法:
2.7.1 GROUP BY
GROUP BY 子句用于将查询结果集中的多行数据根据一个或多个列进行分组。这对于对每个分组的数据进行聚合计算非常有用,如计算每个分组的总和、平均数、最大值、最小值等。
SELECT column_name(s), AGGREGATE_FUNCTION(column_name)
FROM table_name
WHERE condition
GROUP BY column_name(s);
2.7.2 HAVING
HAVING 子句用于对 GROUP BY 生成的分组结果进行条件过滤。它类似于 WHERE 子句,但 WHERE 子句不能与聚合函数一起使用来过滤分组,而 HAVING 可以。
SELECT column_name(s), AGGREGATE_FUNCTION(column_name)
FROM table_name
WHERE condition
GROUP BY column_name(s)
HAVING condition;
这里的 AGGREGATE_FUNCTION() 是指任何聚合函数,如 COUNT(), SUM(), AVG(), MAX(), MIN() 等。
2.7.3 示例语句
假设我们有一个销售数据表 sales,其中包含列 date, region, amount。我们想要找到每个区域的平均销售额,并且只显示平均销售额大于 1000 的区域。
SELECT region, AVG(amount) AS average_sales
FROM sales
GROUP BY region
HAVING AVG(amount) > 1000;
这个查询将首先根据 region 列对数据进行分组,然后计算每个分组的平均销售额,最后使用 HAVING 子句过滤出平均销售额大于 1000 的分组。
请注意,HAVING 子句总是在 GROUP BY 子句之后使用,因为它是对分组结果进行过滤的。如果需要对未分组的原始数据进行过滤,应该使用 WHERE 子句。