写出一个复杂的SQL步骤

简介: 写出一个复杂的SQL步骤

写出一个复杂的SQL步骤



今天就浅显写一篇文章专门介绍数据处理中常见的sql查询场景中的复杂查询。为什么单独说复杂查询呢?因为在业务开发中我们常用orm就可以解决很多查询问题,但是都是比较简单的那种sql,所以orm就能满足。但是一旦涉及到复杂的查询,orm就束手无策了。这个时候我们一般都是写sql查询,但是很多sql还是不太复杂。真正复杂的sql一般都是业务上线之后,领导找你统计各个维度的数据,那么这个时候sql能力就非常重要了,因为它往往涉及很多表很多字段很多子查询。那为了一天就能掌握写复杂sql的能力,为此爆肝这篇文章,一起学习成长。


一. 明确需求


返回所有国家以及相关呼叫的数量及其平均持续通话时间(以秒为单位)。在结果中,仅显示平均呼叫持续时间大于所有呼叫的平均呼叫持续时间的国家。

1. 拆解需求


  1. 需要展示所有国家ID或者国家名称。
  2. 相关呼叫的数量:展示国家的呼叫统计数量。
  3. 平均持续通话时间:展示国家的呼叫平均持续时间,单位:秒。

2. 条件


仅显示平均呼叫持续时间大于所有呼叫的平均呼叫持续时间的国家:

那就是先计算所有呼叫的AVG(endTime-startTime),然后每个国家的平均呼叫时间与它比较即可。


3. 涉及到的表:


  1. 国家:country
  2. 呼叫:call
  3. 城市:city
  4. 用户:customer


为什么需要city和customer表呢?因为call中有外键customer,而customer中有外键city,city中有外键country。


因为要展示所有国家,因此要查询country,而想统计呼叫,就得链接call,怎么能找到call呢,就得从country->city->customer->call。



黑色部分就是需要用到的表


二.开始设计查询


1. 先写出整体框架SQL


通过明确需求得知,我们需要关联四张表:country,city,customer和call。

拆解需求中提到“展示所有国家的名称”,那么这是大前提,因此如果我们想正确使用这些表,我们需要使用外键LEFT JOIN这些表。甚至我们现在不考虑最终查询,我们就知道它将包含以下部分:


SELECT 
 ...
FROM country 
LEFT JOIN city ON city.country_id = country.id
LEFT JOIN customer ON city.id = customer.city_id
LEFT JOIN call ON call.customer_id = customer.id
...;


到这里我们必须做一件事,那就是测试这样的查询返回什么:


SELECT 
 *
FROM country 
LEFT JOIN city ON city.country_id = country.id
LEFT JOIN customer ON city.id = customer.city_id
LEFT JOIN call ON call.customer_id = customer.id;


这一步骤非常必要,因为我们可以看到数据是什么样子的,为后面的查询做好基础。


2. 在添砖加瓦


计算条件中的查询:


SELECT AVG(DATEDIFF(SECOND, call.start_time, call.end_time)) FROM call


DATEDIFF函数计算开始时间和结束时间之间给定时间段(单位:秒)的单位差。


计算相关呼叫的数量:


SUM(CASE WHEN call.id IS NOT NULL THEN 1 ELSE 0 END) AS calls


SUM函数对呼叫统计数量。


计算平均持续通话时间:


AVG(ISNULL(DATEDIFF(SECOND, call.start_time, call.end_time),0)) AS avg_diff


这里大家可能发现我有对NULL做了判断,不管是使用ISNULL函数还是IS NOT NULL判断。为什么呢?因为LEFT JOIN的时候,右边可能出现NULL的情况,我们怎么知道的呢?这就是我们上面提到的:必须将整体SQL框架先打印看结果,知道数据长啥样,自然就知道哪里需要用NULL逻辑特殊处理了


好了,现在可以把这些sql添加到SQL框架中了:


SELECT 
 country.country_name,
 SUM(CASE WHEN call.id IS NOT NULL THEN 1 ELSE 0 END) AS calls,
 AVG(ISNULL(DATEDIFF(SECOND, call.start_time, call.end_time),0)) AS avg_diff
FROM country 
LEFT JOIN city ON city.country_id = country.id
LEFT JOIN customer ON city.id = customer.city_id
LEFT JOIN call ON call.customer_id = customer.id
GROUP BY 
 country.id,
 country.country_name


最后一步:按照条件:“仅显示平均呼叫持续时间大于所有呼叫的平均呼叫持续时间的国家”,我们可以很容易得出,查询最后的结果需要用HAVING对聚合结果做下过滤,因为“所有呼叫的平均呼叫持续时间”和“均呼叫持续时间”我们已经统计出来了,因此大于长这样:


HAVING AVG(ISNULL(DATEDIFF(SECOND, call.start_time, call.end_time),0)) > (SELECT AVG(DATEDIFF(SECOND, call.start_time, call.end_time)) FROM call)


所以最后的SQL长这样:


--返回所有国家以及相关呼叫的数量及其平均持续通话时间(以秒为单位)。在结果中,仅显示平均呼叫持续时间大于所有呼叫的平均呼叫持续时间的国家。
SELECT 
    country.country_name,
    SUM(CASE WHEN call.id IS NOT NULL THEN 1 ELSE 0 END) AS calls,
    AVG(ISNULL(DATEDIFF(SECOND, call.start_time, call.end_time),0)) AS avg_diff
FROM country 
-- 使用LEFT JOIN包括没有任何呼叫的国家
LEFT JOIN city ON city.country_id = country.id
LEFT JOIN customer ON city.id = customer.city_id
LEFT JOIN call ON call.customer_id = customer.id
GROUP BY 
    country.id,
    country.country_name
-- 过滤掉不符合条件的结果
HAVING AVG(ISNULL(DATEDIFF(SECOND, call.start_time, call.end_time),0)) > (SELECT AVG(DATEDIFF(SECOND, call.start_time, call.end_time)) FROM call)


三.总结步骤


  1. 先明确需求
  2. 拆解展示字段和条件
  3. 确定所要用到的表
  4. 先写出整体框架SQL并打印结果看数据很重要这一步
  5. 创建子查询,并且测试结果,最后添加到整体框架SQL中
  6. 测试验证所有数据
  7. 添加备注,复杂SQL不写备注等于没写
相关文章
|
23天前
|
SQL 存储 监控
SQL数据库安装指南:步骤详解与最佳实践
安装和配置SQL数据库可能是一个复杂的过程,但通过遵循本文提供的详细步骤和最佳实践,您可以确保数据库的成功安装和高效运行。无论您是初学者还是经验丰富的数据库管理员,掌握SQL数据库的安装和管理技能都是至关重要的。通过不断学习和实践,您将能够更好地利用SQL数据库来支持您的业务需求和数据分析工作。记住,定期维护和优化数据库是保证其长期性能和稳定性的关键。祝您在安装和配置SQL
|
3月前
|
SQL 存储 BI
sql server 2012远程链接的方法及步骤
sql server 2012远程链接的方法及步骤
|
3月前
|
SQL API 流计算
实时计算 Flink版产品使用合集之在Mac M1下的Docker环境中开启SQL Server代理的操作步骤是什么
实时计算Flink版作为一种强大的流处理和批处理统一的计算框架,广泛应用于各种需要实时数据处理和分析的场景。实时计算Flink版通常结合SQL接口、DataStream API、以及与上下游数据源和存储系统的丰富连接器,提供了一套全面的解决方案,以应对各种实时计算需求。其低延迟、高吞吐、容错性强的特点,使其成为众多企业和组织实时数据处理首选的技术平台。以下是实时计算Flink版的一些典型使用合集。
207 1
|
2天前
|
SQL 关系型数据库 MySQL
SQL自动启动设置指南:详细步骤与技巧
在数据库管理中,确保SQL服务能够自动启动对于保持数据服务的连续性和稳定性至关重要
|
2天前
|
SQL 数据挖掘 数据库
SQL计算班级语文平均分:详细步骤与技巧
在数据库管理中,经常需要统计和查询各种汇总信息,如班级某科目的平均分
|
30天前
|
SQL 索引
业务系统架构实践问题之想要再SQL代码中生成递增序列,那么步骤问题如何解决
业务系统架构实践问题之想要再SQL代码中生成递增序列,那么步骤问题如何解决
|
1月前
|
SQL Java 关系型数据库
Java面试题:描述JDBC的工作原理,包括连接数据库、执行SQL语句等步骤。
Java面试题:描述JDBC的工作原理,包括连接数据库、执行SQL语句等步骤。
35 0
|
3月前
|
SQL 数据处理 HIVE
实时计算 Flink版产品使用合集之将OceanBase的CDC数据导入到Flink SQL的任务的步骤是什么
实时计算Flink版作为一种强大的流处理和批处理统一的计算框架,广泛应用于各种需要实时数据处理和分析的场景。实时计算Flink版通常结合SQL接口、DataStream API、以及与上下游数据源和存储系统的丰富连接器,提供了一套全面的解决方案,以应对各种实时计算需求。其低延迟、高吞吐、容错性强的特点,使其成为众多企业和组织实时数据处理首选的技术平台。以下是实时计算Flink版的一些典型使用合集。
|
2月前
|
SQL 关系型数据库 MySQL
sql数据库建表步骤
在SQL数据库中建表的步骤通常包括以下几个部分: 1. **打开SQL数据库管理工具**: 使用适当的SQL数据库管理工具,如MySQL Workbench、Microsoft SQL
|
3月前
|
SQL 索引