- 查询语句:
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;
- 优化策略:
- 索引优化:
- 在
orders
表的order_id
列上创建索引,这样在JOIN
操作时可以快速定位order_items
表中的相关记录。
CREATE INDEX idx_orders_order_id ON orders(order_id);
- 在
order_items
表的order_id
和product_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 JOIN
或RIGHT JOIN
可能会引入额外的数据扫描,除非确实需要包含一侧表的所有记录。在本查询中,我们只关心有购买行为(即orders
、order_items
和products
表之间有匹配记录)的客户,所以INNER JOIN
是合适的。
- 将聚合操作(如
SUM
和COUNT
)放在GROUP BY
之后,这样数据库可以先进行连接操作并减少数据量,再进行聚合,从而提高效率。
- 使用
HAVING
子句对聚合结果进行筛选,而不是在WHERE
子句中。因为WHERE
子句在聚合之前应用,无法对聚合结果进行过滤,而HAVING
子句专门用于对聚合结果进行条件筛选。