我有以下伪查询有人写道:
SELECT custId, orderId, col1, col2
FROM (SELECT c.id AS custId, o.id AS orderId,
ROW_NUMBER() OVER(PARTITION BY c.id, o.id
ORDER BY d.col1, d.col2) AS RANK
FROM customers c
INNER JOIN orders o ON c.id = o.custId
INNER JOIN orderDetails d ON o.id = d.orderId
WHERE d.col3 IS NULL)
WHERE RANK = 1
不幸的是,这个查询花费了不明的时间(> 2小时),我的任务是解决这个问题。到目前为止,我已经提出了一个运行速度相当快的替代方案(但它仍然是完全不可接受的恕我直言):
SELECT custId, orderId, col1, col2
FROM (SELECT custId, orderId, col1, col2,
ROW_NUMBER() OVER(PARTITION BY custId, orderId
ORDER BY col1, col2) AS RANK
FROM (SELECT c.id AS custId, o.id AS orderId, d.col1, d.col2, d.col3
FROM customers c
INNER JOIN orders o ON c.id = o.custId
INNER JOIN orderDetails d ON o.id = d.orderId)
WHERE col3 IS NULL
WHERE RANK = 1
唉,我无法添加任何索引或查看基于这些表的查询的执行计划,所以我有点不知道如何重写/构造它以显着更快地运行= /。希望你们中的一位专家有一个更好的想法...我不是因为这个特定的查询而特别要求,而是因为我们有很多这样的查询需要像这样重写,我试图了解主要问题是什么这些是/我如何才能最好地解决它们。
答案 0 :(得分:0)
如果没有看到原始查询的解释计划,我现在只能考虑以下查询(可能需要更正语法,但总体思路将保持不变): -
with d as
(select orderid, col1, col2
from (select orderid, col1, col2,
row_number() over (partition by orderID order by col1,col2) as RANK
from orderDetails
where col3 is null)
where RANK=1)
select c.id as custID, o.id as orderID, d.col1, d.col2
from customers c inner join orders o on c.id=o.custID
inner join d on o.id=d.orderid;
您可能需要处理客户,订单和临时表'd'的连接顺序,以便获得正确的组合(以便首先连接具有较少记录数的表)。
在您的查询中,您正在加入表,然后您将获取每个c.id和o.id组合具有最小值col1和col2组的记录。根据您的查询,我认为通过c.id取出分区是安全的,因为col1和col2依赖于orderID而不依赖于customerID。因此,具有相同orderID的多个customerID将具有相同的col1和col2值。
因此,上面的查询首先获取每个orderID的col1和col2组的最小值,然后将它们与其余的表连接起来。