如何优化嵌套的SELECT
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了如何优化嵌套的SELECT相关的知识,希望对你有一定的参考价值。
我有以下需要优化的SQL(在以下代码中,“属性”的名称已更改为更通用):
它在Azure SQL中运行
SELECT ContactValueA, ContactValueB, SUM(X.Price) as Price, SUM(X.ValueX) AS ValueX, SUM(X.ValueY) AS ValueY, Count (*) As [Count]
FROM
(
SELECT OL.id, O.ContactValueA, O.ContactValueB,
OL.Price,
OL.ValueX,
OL.ValueY
FROM [OrderLines] AS OL
JOIN [Orders] AS O
ON OL.OrderId = O.Id
WHERE O.Id in
(
SELECT MIN(SO.Id) AS OID
FROM [Orders] AS SO
WHERE SO.[Type] = 'cake'
AND SO.Created >= @begin and SO.Created < @end
AND NOT EXISTS
(
SELECT 1
FROM [3Orders] AS SOA
WHERE SOA.ExtOrderId = SO.ExtOrderId
AND SOA.[Type] = 'cake'
AND SOA.Created < @begin
)
GROUP BY SO.ExtOrderId
)
) X
GROUP BY X.ContactValueA, X.ContactValueB
@begin和@end都是DateTimeOffset
如果我们看一下代码的这一部分:
SELECT MIN(SO.Id) AS OID
FROM [Orders] AS SO
WHERE SO.[Type] = 'cake'
AND SO.Created >= @begin and SO.Created < @end
AND NOT EXISTS
(
SELECT 1
FROM [3Orders] AS SOA
WHERE SOA.ExtOrderId = SO.ExtOrderId
AND SOA.[Type] = 'cake'
AND SOA.Created < @begin
)
GROUP BY SO.ExtOrderId
关于订单表 - 每个订单都有唯一的ID和非唯一的ExtOrderId - 因为订单表中的条目可以是部分订单(部分订单共享相同的ExtOrderId)
在上面的代码中,我需要查看两个datetimeoffsets之间的所有订单(部分订单) - 并获取具有最低ID的部分订单 - 但是部分订单ID(ExtOrderId)在开始日期之前不得有订单。
有什么建议如何优化?
答案
使用row_number()
解析函数获取最小id
with cte as
(
SELECT OL.id, O.ContactValueA, O.ContactValueB,
OL.Price,
OL.ValueX,
OL.ValueY,
row_number()over(partition by O.type order by o.id) rn
FROM [OrderLines] AS OL
JOIN [Orders] AS O
ON OL.OrderId = O.Id
) ContactValueA, ContactValueB, SUM(Price) as Price, SUM(ValueX) AS ValueX, SUM(ValueY) AS ValueY, Count (*) As [Count] from cte where rn=1
group by ContactValueA, ContactValueB
另一答案
试试吧
WITH T AS (
SELECT MIN(SO.Id) AS OID
FROM [Orders] AS SO
WHERE SO.[Type] = 'cake' AND SO.Created < @end
GROUP BY SO.ExtOrderId
HAVING MIN(SO.Created) >= @begin
), T1 AS (
SELECT OL.id, O.ContactValueA, O.ContactValueB,
OL.Price,
OL.ValueX,
OL.ValueY
FROM [OrderLines] AS OL
INNER JOIN T ON T.OID = OL.OrderId
INNER JOIN [Orders] AS O ON T.OID = O.Id
) SELECT ContactValueA, ContactValueB, SUM(T1.Price) as Price, SUM(T1.ValueX) AS ValueX, SUM(T1.ValueY) AS ValueY, Count (*) As [Count]
FROM T1
GROUP BY T1.ContactValueA, T1.ContactValueB
另一答案
我将使用左连接并返回没有找到先前订单的行,而不是使用子查询。
您的查询 :
SELECT MIN(SO.Id) AS OID
FROM [Orders] AS SO
WHERE SO.[Type] = 'cake'
AND SO.Created >= @begin and SO.Created < @end
AND NOT EXISTS
(
SELECT 1
FROM [3Orders] AS SOA
WHERE SOA.ExtOrderId = SO.ExtOrderId
AND SOA.[Type] = 'cake'
AND SOA.Created < @begin
)
GROUP BY SO.ExtOrderId
将会 :
SELECT MIN(SO.Id) AS OID
FROM [Orders] AS SO
LEFT JOIN [3Orders] AS SOA ON SOA.ExtOrderId = SO.ExtOrderId
AND SOA.[Type] = 'cake'
AND SOA.Created < @begin
WHERE SO.[Type] = 'cake'
AND SO.Created >= @begin and SO.Created < @end
AND SOA.Id IS NULL -- Here we ensure that it has no previous orders
GROUP BY SO.ExtOrderId
以上是关于如何优化嵌套的SELECT的主要内容,如果未能解决你的问题,请参考以下文章