WITH -- 定义一个子查询,获取销售额排名前10的产品 top_products AS ( SELECT product_id, SUM(sales) AS total_sales FROM orders WHERE order_date BETWEEN '2021-01-01' AND '2021-06-30' GROUP BY product_id ORDER BY total_sales DESC LIMIT 10 ), -- 定义一个子查询,获取销售额排名前10的客户 top_customers AS ( SELECT customer_id, SUM(sales) AS total_sales FROM orders WHERE order_date BETWEEN '2021-01-01' AND '2021-06-30' GROUP BY customer_id ORDER BY total_sales DESC LIMIT 10 ), -- 定义一个窗口函数,计算每个客户的销售额排名 customer_sales_rank AS ( SELECT customer_id, SUM(sales) AS total_sales, ROW_NUMBER() OVER (ORDER BY SUM(sales) DESC) AS sales_rank FROM orders WHERE order_date BETWEEN '2021-01-01' AND '2021-06-30' GROUP BY customer_id ) -- 最终查询,获取纽约市销售额排名前10的客户,以及他们购买的销售额排名前10的产品 SELECT customers.id AS customer_id, customers.name AS customer_name, products.id AS product_id, products.name AS product_name, SUM(orders.sales) AS total_sales FROM orders -- 连接顾客信息 INNER JOIN customers ON orders.customer_id = customers.id -- 连接产品信息 INNER JOIN products ON orders.product_id = products.id -- 仅查询纽约市的客户 WHERE customers.city = 'New York' -- 仅查询销售额排名前10的客户 AND customers.id IN (SELECT customer_id FROM top_customers) -- 仅查询销售额排名前10的产品 AND products.id IN (SELECT product_id FROM top_products) -- 仅查询客户销售额排名前10的订单 AND customers.id IN (SELECT customer_id FROM customer_sales_rank WHERE sales_rank <= 10) GROUP BY customers.id, customers.name, products.id, products.name ORDER BY customers.id, total_sales DESC, products.id;请优化下这条sql
时间: 2024-03-10 14:49:54 浏览: 117
这条 SQL 查询已经比较优化了,但是仍然可以进行如下优化:
1. 在 `top_products` 和 `top_customers` 子查询中,可以使用 `WITH RECURSIVE` 子句来代替 `LIMIT` 子句,以获取销售额排名前 10 的记录。
2. 可以将子查询 `customer_sales_rank` 的结果存储到临时表中,以避免在最终查询中重复计算。
3. 可以将 `INNER JOIN` 改为 `LEFT JOIN`,这样可以包括那些没有销售记录的客户和产品。
4. 可以使用 `EXISTS` 子句代替 `IN` 子句,以提高查询效率。
优化后的 SQL 查询如下:
```
WITH RECURSIVE top_products AS (
SELECT product_id, SUM(sales) AS total_sales
FROM orders
WHERE order_date BETWEEN '2021-01-01' AND '2021-06-30'
GROUP BY product_id
ORDER BY total_sales DESC
LIMIT 10
), top_customers AS (
SELECT customer_id, SUM(sales) AS total_sales
FROM orders
WHERE order_date BETWEEN '2021-01-01' AND '2021-06-30'
GROUP BY customer_id
ORDER BY total_sales DESC
LIMIT 10
), customer_sales_rank AS (
SELECT customer_id, SUM(sales) AS total_sales, ROW_NUMBER() OVER (ORDER BY SUM(sales) DESC) AS sales_rank
FROM orders
WHERE order_date BETWEEN '2021-01-01' AND '2021-06-30'
GROUP BY customer_id
)
SELECT c.id AS customer_id, c.name AS customer_name, p.id AS product_id, p.name AS product_name, SUM(o.sales) AS total_sales
FROM customers c
LEFT JOIN orders o ON c.id = o.customer_id
LEFT JOIN products p ON o.product_id = p.id
WHERE c.city = 'New York'
AND EXISTS (
SELECT 1 FROM top_customers WHERE customer_id = c.id
)
AND EXISTS (
SELECT 1 FROM top_products WHERE product_id = p.id
)
AND EXISTS (
SELECT 1 FROM customer_sales_rank WHERE customer_id = c.id AND sales_rank <= 10
)
GROUP BY c.id, c.name, p.id, p.name
ORDER BY c.id, total_sales DESC, p.id;
```
阅读全文