MST

星途 面试题库

面试题:MySQL复杂查询场景下避免不必要数据请求策略

有三个表,`orders`表(`order_id`、`customer_id`、`order_date`),`order_items`表(`item_id`、`order_id`、`product_id`、`quantity`),`products`表(`product_id`、`product_name`、`price`)。要统计每个客户购买的不同产品数量以及总花费,并只显示总花费大于1000的客户信息。写出查询语句,并详细说明在这个复杂查询过程中,如何通过索引、查询逻辑调整等方式避免不必要的数据请求。
24.6万 热度难度
数据库MySQL

知识考点

AI 面试

面试题答案

一键面试
  1. 查询语句
SELECT 
    o.customer_id,
    COUNT(DISTINCT oi.product_id) AS distinct_product_count,
    SUM(p.price * oi.quantity) AS total_spend
FROM 
    orders o
JOIN 
    order_items oi ON o.order_id = oi.order_id
JOIN 
    products p ON oi.product_id = p.product_id
GROUP BY 
    o.customer_id
HAVING 
    SUM(p.price * oi.quantity) > 1000;
  1. 优化策略
    • 索引优化
      • orders表的order_id列上创建索引,这样在JOIN操作时可以快速定位order_items表中的相关记录。
      CREATE INDEX idx_orders_order_id ON orders(order_id);
      
      • order_items表的order_idproduct_id列上分别创建索引。order_id索引用于连接orders表,product_id索引用于连接products表。
      CREATE INDEX idx_order_items_order_id ON order_items(order_id);
      CREATE INDEX idx_order_items_product_id ON order_items(product_id);
      
      • products表的product_id列上创建索引,以加快与order_items表的连接。
      CREATE INDEX idx_products_product_id ON products(product_id);
      
    • 查询逻辑调整
      • 确保JOIN条件尽可能简单和直接,避免在JOIN条件中使用函数或复杂表达式,因为这可能会阻止索引的使用。
      • 尽量使用INNER JOIN,因为LEFT JOINRIGHT JOIN可能会引入额外的数据扫描,除非确实需要包含一侧表的所有记录。在本查询中,我们只关心有购买行为(即ordersorder_itemsproducts表之间有匹配记录)的客户,所以INNER JOIN是合适的。
      • 将聚合操作(如SUMCOUNT)放在GROUP BY之后,这样数据库可以先进行连接操作并减少数据量,再进行聚合,从而提高效率。
      • 使用HAVING子句对聚合结果进行筛选,而不是在WHERE子句中。因为WHERE子句在聚合之前应用,无法对聚合结果进行过滤,而HAVING子句专门用于对聚合结果进行条件筛选。