【SQL语言实战指南】:课后习题SQL编写与优化技巧:提升SQL技能的三大步骤
发布时间: 2025-01-05 10:44:37 阅读量: 18 订阅数: 19 


SQL Server——从入门到放弃(15)– 第九章: 关系查询处理和查询优化 课后习题

# 摘要
本文针对SQL语言的多个层面进行了深入探讨,包括基础知识回顾、编写实践技巧、查询优化技巧、进阶脚本编写、不同数据库系统中的应用差异,以及综合案例与实战演练。通过剖析SELECT语句的结构、表连接技术、数据操作语句的优化方法、事务处理、索引类型、SQL执行计划,以及存储过程、函数、视图的应用,本文旨在提升读者的SQL编写和优化能力。此外,文章还探讨了如何应对不同数据库系统的SQL应用差异,为数据库开发者和维护者提供了实用的技能提升方案和实战案例分析。
# 关键字
SQL语言;查询优化;数据操作;索引;事务控制;脚本编写
参考资源链接:[数据库系统教程(第3版)课后习题答案](https://wenku.csdn.net/doc/dml0p00027?spm=1055.2635.3001.10343)
# 1. SQL语言基础知识回顾
SQL(Structured Query Language)是数据库领域中不可或缺的编程语言,用于管理和操作关系型数据库。尽管它的语法在不同数据库系统中存在差异,但核心概念保持一致。本章将从基础出发,回顾SQL语言的核心组成,包括数据定义语言(DDL)、数据操作语言(DML)和数据控制语言(DCL)。
## SQL语言的核心组成
SQL语言的主要组成部分涵盖了创建和修改数据库结构的DDL,如创建表(CREATE TABLE)、修改表结构(ALTER TABLE)和删除表(DROP TABLE)等。DML则涉及数据的增删改查操作,包括SELECT、INSERT、UPDATE和DELETE语句。DCL则包括授权(GRANT)和收回权限(REVOKE)等操作,用于数据库安全管理。
## SQL数据类型和函数
理解SQL中的数据类型是编写有效查询的基础。数据类型定义了列可以存储的数据种类,如整数(INTEGER)、浮点数(FLOAT)、字符(CHAR)和日期(DATE)等。同时,内置函数在数据处理和转换中扮演着重要角色,包括聚合函数(COUNT、SUM、AVG)、字符串函数(CONCAT、LENGTH)、日期函数(CURDATE、NOW)等。深入学习这些函数对于数据提取和预处理至关重要。
通过本章的回顾,我们将为深入探索SQL的高级特性和优化技巧打下坚实的基础。接下来,我们将进入SQL编写实践技巧,探索如何构建高效和优化的SQL查询语句。
# 2. SQL编写实践技巧
## 2.1 理解SQL查询的构建
### 2.1.1 SELECT语句的结构和用法
编写一个有效的SQL查询是数据操作的基础。首先,让我们回顾一下SELECT语句的基本结构。一个基本的SELECT语句由以下部分组成:
```sql
SELECT column1, column2, ...
FROM table_name
WHERE condition
GROUP BY column
HAVING condition
ORDER BY column;
```
- `SELECT` 关键字用于指定要查询的列。
- `FROM` 关键字指定了要从哪个表中检索数据。
- `WHERE` 子句用于过滤记录,只允许符合特定条件的记录进入结果集。
- `GROUP BY` 子句按照一个或多个列对结果集进行分组。
- `HAVING` 子句与`GROUP BY`结合使用,用于对分组后的结果进行过滤。
- `ORDER BY` 子句用于对结果集进行排序。
每一个部分都有其重要性,而且它们可以被组合起来使用以满足不同的查询需求。在编写查询时,你应该从需要显示哪些列开始思考,然后选择合适的表,以及最终确定是否需要过滤、分组和排序数据。
举一个例子:
```sql
SELECT customer_name, SUM(amount) as total_sales
FROM sales
WHERE sale_date BETWEEN '2023-01-01' AND '2023-01-31'
GROUP BY customer_name
HAVING total_sales > 1000
ORDER BY total_sales DESC;
```
这个查询将返回所有在一月内销售总额超过1000的客户的名称和销售总额,结果集按总销售金额降序排列。
### 2.1.2 表连接(JOIN)的高级技巧
表连接(JOINs)是SQL中用于从多个表中提取数据的强大工具。表连接可以基于相等条件(内连接)、基于不等条件(外连接)、自然连接等多个条件来实现。
例如:
```sql
SELECT customers.customer_name, orders.order_id, orders.order_date
FROM customers
INNER JOIN orders
ON customers.customer_id = orders.customer_id;
```
这个查询展示了如何通过`INNER JOIN`来合并两个表:`customers`和`orders`。只有在两个表中都能找到匹配的`customer_id`时,才会返回记录。
高级技巧:
- 使用`LEFT JOIN`(或`RIGHT JOIN`)来获取左表(或右表)的所有记录,即使在另一张表中没有匹配的记录。
- 使用`CROSS JOIN`(笛卡尔积)来创建两个表的组合,每一对可能的组合都会被返回。
- 当使用连接时,尽可能地指定连接条件,并使用明确的列名来提高代码的可读性和性能。
务必理解不同类型的JOINs以及它们的使用场景,这样可以确保你能够从多个表中获取所需的数据,同时保持查询的效率和准确性。
# 3. SQL查询优化技巧
## 理解索引的作用
### 索引类型及其适用场景
索引在数据库查询中扮演着关键角色,它是一种数据结构,可以帮助快速定位数据,极大地提高查询效率。理解索引的不同类型及其适用场景,是实现高效SQL查询的关键。
#### 1. B-Tree索引
B-Tree索引是最常见的索引类型,适用于全键值、键值范围或键值前缀查找。这种索引能够保持数据有序,因此对排序操作也有好处。它特别适用于主键查询以及WHERE子句中对列进行比较的查询。
#### 2. 哈希索引
哈希索引基于哈希表实现,适用于等值查询(=),但不适用于范围查询(>,<)。它们的构建速度快,但如果数据需要进行范围查询或排序,哈希索引的表现就不是很理想。
#### 3. 空间索引
空间索引用于对空间数据类型列进行索引,可以高效地执行包含几何数据的查询。适用于地理信息系统(GIS)和其他需要处理空间数据的应用。
#### 4. 全文索引
全文索引专用于搜索文本数据中的关键字,适用于大量的文本数据。它能够提高文本搜索的性能,并常用于搜索引擎和数据挖掘。
### 创建和维护索引的最佳实践
#### 选择合适的列建立索引
要根据查询模式选择索引列。经常用于WHERE子句、JOIN条件、ORDER BY或GROUP BY子句中的列,都是创建索引的良好候选者。
#### 考虑索引的维护成本
索引虽然可以提高查询效率,但其本身也需要额外的空间,并在每次数据修改操作(如INSERT、UPDATE或DELETE)时都需要维护。因此,需要权衡索引带来的性能提升与维护成本之间的关系。
#### 使用索引覆盖查询
如果一个查询可以通过读取索引来得到结果,而不需要访问数据行,那么这样的查询被称为“索引覆盖查询”。这种查询的执行速度会非常快。
#### 避免过度索引
虽然索引可以提高查询性能,但过多的索引会降低数据插入、更新和删除的性能,因为需要同时维护更多的索引结构。
## SQL执行计划分析
### 如何解读执行计划
SQL执行计划是数据库执行器用来展示如何执行一个查询语句的内部表示。理解执行计划是优化查询的关键步骤。执行计划通常包含以下几个部分:
#### 1. 操作类型
执行计划中的每个步骤通常对应一个操作类型,如“全表扫描”、“索引扫描”、“连接操作”等。
#### 2. 输出列
指出每个操作所输出的列,这对于理解如何从多个表中聚合数据至关重要。
#### 3. 访问方法
即数据库如何访问存储的数据,例如“通过索引访问数据”、“顺序扫描”。
#### 4. 成本信息
执行计划可能还会提供每个操作的预计成本,以帮助优化者了解查询的性能瓶颈。
### 识别和解决查询性能瓶颈
通过分析执行计划,可以发现查询的性能瓶颈,如不必要的全表扫描、排序操作或是过多的数据行需要被处理。
#### 1. 优化数据访问
检查是否有不必要的列被包括在索引中,这可能会导致写操作的性能下降,同时增加存储成本。
#### 2. 改进连接操作
对于使用了JOIN的查询,检查是否正确使用了索引,并考虑是否可以利用内连接(INNER JOIN)代替其他连接类型。
#### 3. 减少排序开销
如果执行计划中包含排序操作,考虑是否可以通过索引预先排序或调整查询语句避免排序。
## SQL优化案例研究
### 常见SQL性能问题剖析
#### 1. 慢查询
慢查询是性能问题中最常见的一种,可能是由于全表扫描、索引缺失或不当使用数据类型等原因导致。
#### 2. 锁争用
当多个事务同时访问同一数据时,可能会导致锁争用问题,进而影响查询性能。
#### 3. 查询优化器选择不佳
查询优化器可能无法总是选择最优的执行计划,特别是当统计信息过时或查询模式复杂时。
### 实际案例中的优化技巧应用
#### 1. 重新构建查询语句
优化查询的一个常见方法是重写查询语句,以减少需要处理的数据量或更有效地使用索引。
#### 2. 分析查询执行计划
通过分析执行计划,可以确定数据库执行查询的方式,并发现可能的性能问题。
#### 3. 应用索引技巧
索引是提升查询性能最有效的工具之一,根据查询的需要,选择合适的索引策略至关重要。
### 代码块与参数说明
```sql
-- 一个典型的创建索引的例子
CREATE INDEX idx_customers_name ON customers(name);
```
在上述例子中,我们创建了一个名为idx_customers_name的索引,用于加速基于name列的查询。这里使用的是B-Tree索引,适用于大多数基于值查找的场景。
```sql
-- 使用EXPLAIN关键字查看SQL执行计划
EXPLAIN SELECT * FROM orders WHERE order_date > '2021-01-01';
```
此代码段演示了如何使用EXPLAIN关键字来获取关于特定查询的执行计划。这有助于我们理解数据库是如何处理这个查询的,并且可以发现查询性能问题。
```sql
-- 分析查询性能瓶颈,考虑索引
SELECT order_id, customer_id FROM orders WHERE order_date > '2021-01-01' AND customer_id IN (SELECT id FROM customers WHERE country = 'USA');
```
此查询需要从orders表和customers表中联合查询数据,索引优化需要考虑如何在两张表中有效地利用索引。
### 优化前后的性能对比
对比执行优化前后的查询,可以直观地看到性能的提升。下面是一个典型的性能提升例子:
- **优化前**:查询耗时5秒,返回5000条数据。
- **优化后**:查询耗时0.5秒,返回相同数据量。
### 表格:性能优化前后对比
| 度量 | 优化前 | 优化后 |
|---|---|---|
| 查询耗时 | 5秒 | 0.5秒 |
| 返回数据行数 | 5000行 | 5000行 |
| 索引使用情况 | 无索引 | 有索引 |
| 数据访问方式 | 全表扫描 | 索引扫描 |
通过上述表格,我们可以清晰地看到性能优化前后的对比,以及性能提升的原因。
# 4. SQL脚本编写进阶技巧
## 4.1 规范化与反规范化策略
数据库设计是一个确保数据质量和完整性、优化查询性能的过程。规范化是其中的一个重要方面,它涉及将数据组织成多个相关联的表,以减少冗余和提高数据的一致性。然而,过度规范化可能会影响查询性能,这时就需要反规范化来提高数据访问速度。
### 4.1.1 数据库设计原则与反规范化的影响
数据库规范化有多个范式,包括第一范式(1NF)、第二范式(2NF)、第三范式(3NF),以及更高级的范式。这些范式有助于确保数据的结构合理和减少数据冗余。但是,规范化也有其缺点:
- 数据库查询可能会涉及多个表的连接操作,这会增加数据库的处理时间。
- 复杂的SQL查询可能难以理解和维护。
- 数据库在大量表上执行连接操作时,其性能可能会受到影响。
反规范化通过合并表、引入冗余列、创建汇总表等方法来优化性能,但同时会增加数据冗余和维护成本。因此,实施反规范化需要仔细权衡其对性能的提升与对数据完整性的潜在影响。
### 4.1.2 根据业务需求平衡规范化与反规范化
在实际应用中,规范化和反规范化的平衡需要基于业务需求来决策。例如:
- 如果业务逻辑需要频繁地汇总大量数据,可能需要创建汇总表来加快查询速度。
- 在数据更新不是非常频繁的系统中,可以适当引入冗余数据来减少连接操作。
- 如果查询性能是关键因素,可能需要在数据模型中加入冗余字段。
对于数据仓库和数据集市这类系统,反规范化通常是常见的实践,因为它们更注重数据读取的性能。而在事务处理系统中,则通常需要更多的规范化来保持数据的一致性和减少更新异常。
## 4.2 SQL脚本的模块化和复用
编写可维护且高效的SQL脚本需要利用数据库提供的高级特性,如存储过程、函数、视图和临时表。这些特性可以让SQL代码更加模块化,易于复用,有助于降低维护成本。
### 4.2.1 存储过程和函数的编写与优化
存储过程和函数是数据库中可以存储的一组SQL语句,它们可以接受参数并返回结果。它们的特点是:
- **模块化:** 它们将功能封装成一个单元,可以被多次调用。
- **性能提升:** 在数据库服务器上执行,减少了客户端和服务器之间的通信开销。
- **安全性:** 可以限制对数据库的直接访问,通过抽象操作来保护数据。
编写和优化存储过程和函数时,需要考虑:
- **逻辑清晰:** 使用适当的逻辑分块,使得代码易于阅读和维护。
- **参数化:** 尽可能使用参数化查询,避免SQL注入风险。
- **执行效率:** 优化查询语句,减少不必要的数据处理。
- **错误处理:** 使用异常处理机制来捕获和响应错误。
### 4.2.2 视图和临时表在SQL脚本中的应用
视图是虚拟表,它们是基于SQL语句的结果集。视图可以用作简化复杂的SQL操作,或者向用户提供一个只包含所需字段的表的“窗口”。临时表则用于存储临时数据,可以是局部的(在存储过程或批处理内)或全局的(整个数据库会话中可见)。
在SQL脚本中,视图和临时表可以用于:
- **数据抽象:** 通过视图提供数据的抽象层,隐藏底层数据结构的复杂性。
- **中间结果存储:** 使用临时表保存中间查询结果,简化复杂操作。
- **性能优化:** 通过预计算复杂查询并存储结果在临时表中,提高后续查询的性能。
使用视图和临时表时,需要注意:
- **性能:** 对于视图,如果视图定义中有大量数据处理,每次查询视图时都可能导致性能下降。临时表也可能占用额外的存储空间。
- **更新限制:** 并非所有视图都能进行数据更新操作,特别是那些包含聚合或多个表的视图。
- **生命周期:** 视图和临时表都有一定的生命周期,视图在数据库中一直存在,直到被显式删除;临时表则随着会话的结束而消失。
## 4.3 SQL脚本的错误处理和日志记录
在SQL脚本编写中,错误处理和日志记录是保证系统稳定性和可追溯性的关键因素。它们有助于诊断问题并防止未来的错误。
### 4.3.1 SQL错误处理机制
大多数数据库管理系统提供了错误处理的机制。在SQL中,可以使用`TRY...CATCH`(在支持该语法的数据库系统中)、`EXCEPTION`(在一些数据库如Oracle中)或者错误代码检测等方法来捕捉和处理执行时出现的错误。
错误处理的一般步骤包括:
1. **捕获错误:** 使用适当的语句捕捉SQL执行过程中产生的错误。
2. **日志记录:** 记录错误的详细信息,如错误代码、消息和发生错误时的上下文。
3. **恢复和清理:** 在错误发生后,执行适当的清理操作和恢复步骤,以确保数据库的一致性。
4. **反馈:** 向用户或者应用程序提供错误信息。
### 4.3.2 日志记录在故障排查中的重要性
日志记录是记录系统操作和错误发生情况的重要手段。它可以帮助DBA和开发者了解系统的行为,并在问题出现时提供诊断信息。在SQL脚本中,日志记录通常包括:
- **执行时间:** 操作开始和结束的时间戳,可以用来计算操作耗时。
- **操作类型:** 执行的是查询、更新、插入还是删除操作。
- **影响行数:** 操作影响的行数。
- **错误信息:** 如果操作失败,需要记录详细的错误信息。
- **用户上下文:** 发起操作的用户信息和相关的会话信息。
日志记录时应该遵循的最佳实践包括:
- **最小化性能影响:** 日志记录应尽可能减少对性能的影响,尤其是在高并发的生产环境中。
- **信息的充分性:** 记录的信息应足够详细,以帮助问题追踪和分析。
- **安全性和隐私:** 确保日志记录不会泄露敏感数据。
通过结合数据库提供的错误处理和日志记录功能,我们可以构建一个更为健壮和可靠的SQL脚本执行环境。这有助于我们更好地进行问题定位和故障排查,确保业务数据的稳定性和安全性。
# 5. SQL在不同数据库系统中的应用差异
## 5.1 跨平台SQL语言特性对比
### 5.1.1 不同数据库系统对SQL标准的支持情况
SQL(Structured Query Language)作为一种国际标准的数据库查询语言,广泛应用于各种关系型数据库管理系统(RDBMS)。然而,尽管所有支持SQL的数据库系统都遵循ANSI SQL标准,但是每个数据库厂商在实现时都有自己的扩展和特殊功能,这使得在不同数据库系统中编写SQL代码时可能会遇到差异。
以Oracle、MySQL和SQL Server为例,三者虽然都支持基本的SQL语法,但是在内置函数、数据类型、事务处理等方面存在差异。例如:
- **Oracle** 强调PL/SQL的支持,有着自己复杂的权限管理和数据库对象。
- **MySQL** 在开源数据库领域被广泛使用,对于存储过程和函数的支持比较基础。
- **SQL Server** 则提供了丰富的T-SQL特定功能,如表值参数和输出参数等。
理解这些差异对于维护跨平台兼容性至关重要。开发者在编写跨平台应用时,需要尽量使用标准SQL来保证代码的可移植性,同时编写数据库抽象层或适配层以隐藏不同数据库之间的差异。
### 5.1.2 数据库特定功能的使用和迁移策略
每个数据库系统都有其独特的功能和最佳实践。开发者在进行数据库迁移或开发新系统时,如何利用这些特性是关键。
以索引为例,不同数据库对索引类型的实现不尽相同。Oracle提供了位图索引(Bitmap Indexes),而MySQL支持全文索引(Full-Text Index)。了解这些特性能够帮助开发者提升查询效率,优化数据库性能。
当需要迁移SQL代码时,一个有效的策略是:
1. **代码审计**: 检查现有的SQL代码,识别出不符合标准的SQL语句或特定数据库的函数和数据类型。
2. **抽象化**: 创建数据库抽象层,将数据库特定的代码封装起来,使得上层应用只依赖于抽象接口。
3. **迁移计划**: 根据迁移目标数据库的功能集制定详细计划,按优先级迁移和重构代码。
4. **测试**: 详细测试迁移后的代码,确保数据一致性和性能达到预期。
## 5.2 优化SQL以适应不同数据库性能
### 5.2.1 数据库优化器的工作原理
数据库优化器是数据库管理系统中的一个关键组件,负责将SQL查询转换成执行计划,并选择最有效的执行路径。不同的数据库系统有其独特的优化器算法和查询处理机制。
例如,**Oracle优化器**会基于成本进行选择最佳执行计划,而**SQL Server**使用启发式方法来估算执行计划的成本。这些优化器会考虑统计信息、索引可用性、表大小等多种因素。
开发者了解数据库优化器的工作原理对于编写高效的SQL至关重要。例如,理解如何通过统计信息更新来影响优化器的选择,或者如何通过编写提示(hint)来强制数据库执行特定路径的查询。
### 5.2.2 根据数据库特性调整SQL编写
针对数据库的特性调整SQL编写可以显著提升性能。比如,对于复杂的查询和报表,可以考虑使用数据库特定的高级函数和构造来简化SQL代码。
- **Oracle**: 可以利用其提供的高级聚合函数(如 Analytics Functions)进行复杂的分析处理。
- **MySQL**: 对于OLTP(Online Transaction Processing)场景,应优化使用InnoDB存储引擎的特性。
- **SQL Server**: 可以使用其提供的窗口函数(Window Functions)进行复杂的数据分析。
开发者在编写跨平台的SQL代码时,应尽量利用数据库提供的高级特性和功能,但同时也要注意保持代码的可移植性。为了适应不同的数据库性能,可以采取以下策略:
1. **性能分析**: 使用数据库提供的工具进行性能分析,识别查询中的性能瓶颈。
2. **查询重写**: 根据性能分析结果,对查询进行重写,以提高性能。
3. **功能测试**: 对重写的查询进行功能和性能测试,确保无误并且有性能提升。
4. **持续监控**: 在生产环境中持续监控SQL性能,确保优化效果。
```sql
-- 示例代码段:Oracle Analytics Function使用
SELECT employee_id, department_id, salary,
LAG(salary, 1) OVER (PARTITION BY department_id ORDER BY employee_id) AS prev_salary
FROM employees;
```
在上述Oracle示例中,我们使用了`LAG`窗口函数来获取当前行的前一行值。窗口函数允许用户在单个查询中执行复杂的分析,是数据库特定优化的一部分。
总结而言,根据不同的数据库系统调整SQL代码以优化性能,需要开发者具备对数据库优化器工作原理和数据库特性深入了解。通过持续的性能分析和调优,可以确保在不同数据库系统之间获得最佳性能。
# 6. 提升SQL技能的综合案例与实战演练
## 6.1 综合案例分析
在这一节中,我们将深入探讨复杂业务场景下的SQL设计,并且分析从需求到SQL实现的整个转化过程。
### 6.1.1 复杂业务场景下的SQL设计
在实际的业务环境中,经常遇到复杂的业务逻辑需要转化为SQL语句。以电子商务平台的订单处理系统为例,我们可能需要查询满足特定条件的订单数据,如不同时间区间、不同用户等级以及不同的支付状态。
```sql
SELECT o.order_id, o.order_date, u.user_level, p.payment_status
FROM orders o
JOIN users u ON o.user_id = u.user_id
JOIN payments p ON o.payment_id = p.payment_id
WHERE o.order_date BETWEEN '2023-01-01' AND '2023-01-31'
AND u.user_level = 'VIP'
AND p.payment_status = 'Completed';
```
这个查询展示了如何通过JOIN语句来联合多个表,以实现对订单数据的多维度筛选。在设计这样的查询时,需要考虑索引的使用以及表连接的顺序,这将直接影响查询的性能。
### 6.1.2 从需求到SQL实现的转化过程
从需求到SQL实现的转化过程,是将业务逻辑细化到数据库能够理解的语言的过程。例如,业务部门提出需求:“我需要知道上周每个用户的订单总金额,并按照总金额降序排列。”
这个需求可以转化为以下SQL语句:
```sql
SELECT u.user_id, u.user_name, SUM(o.order_amount) AS total_order_amount
FROM orders o
JOIN users u ON o.user_id = u.user_id
WHERE o.order_date BETWEEN '2023-02-01' AND '2023-02-07'
GROUP BY u.user_id, u.user_name
ORDER BY total_order_amount DESC;
```
在实现过程中,我们需要考虑如何使用GROUP BY语句来聚合数据,以及如何使用WHERE语句来筛选特定时间范围内的记录。
## 6.2 实战演练与技能提升
### 6.2.1 真实业务问题的SQL编写和优化
现在,让我们来解决一个更具体的业务问题。假设我们有一个报表需求,需要统计每个产品的销售数量和销售总额,以确定哪些产品最受欢迎,并且贡献了最大的收入。
```sql
SELECT p.product_name, SUM(od.quantity) AS total_quantity_sold,
SUM(od.quantity * od.unit_price) AS total_sales_amount
FROM order_details od
JOIN products p ON od.product_id = p.product_id
GROUP BY p.product_id, p.product_name
ORDER BY total_sales_amount DESC;
```
这个查询通过连接`order_details`和`products`表,使用GROUP BY语句来统计销售数据,并通过ORDER BY语句来对结果进行排序。
在编写查询后,我们应进行性能分析和优化。优化可能包括添加适当的索引,重写查询以减少表扫描,并可能采用批处理技术对大量数据进行处理。
### 6.2.2 技术讨论区的SQL挑战与解决方案分享
在技术社区或讨论区中,经常会遇到各种各样的SQL挑战。这些挑战可能涉及特定的SQL函数应用、复杂的表连接逻辑、性能优化,或者是在特定数据库系统中实现特定功能。
例如,考虑这样一个挑战:在不使用临时表的情况下,找出销售数量最多的前10个产品。解决这个问题可以使用窗口函数(Window Functions),如ROW_NUMBER():
```sql
SELECT product_name, total_quantity_sold, total_sales_amount
FROM (
SELECT p.product_name,
SUM(od.quantity) AS total_quantity_sold,
SUM(od.quantity * od.unit_price) AS total_sales_amount,
ROW_NUMBER() OVER(ORDER BY SUM(od.quantity * od.unit_price) DESC) as rank
FROM order_details od
JOIN products p ON od.product_id = p.product_id
GROUP BY p.product_name
) ranked_products
WHERE rank <= 10;
```
上述查询使用了一个子查询和窗口函数ROW_NUMBER()来实现挑战要求,同时保持查询的高效性。
通过解决这些挑战,我们不仅能够提升自己的SQL技能,还能从社区中学习到更多的实践经验和创新解决方案。
0
0
相关推荐







