MST

星途 面试题库

面试题:复杂MySQL关联查询的性能分解

假设有三个表`orders`(包含`order_id`,`customer_id`,`order_date`),`customers`(包含`customer_id`,`customer_name`,`region`),`order_items`(包含`order_item_id`,`order_id`,`product_id`,`quantity`)。现在要查询每个地区在过去一个月内订单总数量排名前三的客户及其订单数量。请阐述如何分解这个关联查询来提升性能,并给出优化后的SQL语句。
21.3万 热度难度
数据库MySQL

知识考点

AI 面试

面试题答案

一键面试
  1. 分解查询步骤以提升性能
    • 第一步:确定过去一个月的时间范围。这可以通过数据库的日期函数来实现,不同数据库函数略有不同,例如在MySQL中,可以使用CURRENT_DATE获取当前日期,然后通过INTERVAL关键字来计算一个月前的日期。
    • 第二步:先关联orderscustomers表,基于customer_id字段,这样可以得到每个订单对应的客户信息以及地区信息。
    • 第三步:再关联order_items表和前面得到的结果集,基于order_id字段,从而可以统计每个客户的订单数量。
    • 第四步:按照地区和客户订单数量进行分组和排序,使用窗口函数来获取每个地区订单总数量排名前三的客户。
  2. 优化后的SQL语句(以MySQL为例)
WITH recent_orders AS (
    SELECT o.order_id, o.customer_id, o.order_date, c.customer_name, c.region, oi.quantity
    FROM orders o
    JOIN customers c ON o.customer_id = c.customer_id
    JOIN order_items oi ON o.order_id = oi.order_id
    WHERE o.order_date >= CURDATE() - INTERVAL 1 MONTH
),
ranked_customers AS (
    SELECT region, customer_name, SUM(quantity) AS total_quantity,
        RANK() OVER (PARTITION BY region ORDER BY SUM(quantity) DESC) AS ranking
    FROM recent_orders
    GROUP BY region, customer_name
)
SELECT region, customer_name, total_quantity
FROM ranked_customers
WHERE ranking <= 3;

在上述SQL中:

  • WITH子句创建了两个临时表。recent_orders临时表通过多表关联得到过去一个月内每个订单的详细信息。
  • ranked_customers临时表对recent_orders按地区和客户分组,统计订单总数量并使用RANK()窗口函数按订单总数量降序排名。
  • 最后从ranked_customers中选择排名前三的客户及其订单数量。这样的查询结构有助于数据库查询优化器更好地理解查询意图,从而提升性能。