我有以下需要优化的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)不得在开始日期之前有订单。
有人建议如何优化它吗?
答案 0 :(得分:0)
使用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
答案 1 :(得分:0)
我将使用左联接而不返回子查询,而不使用子查询。
您的查询:
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
答案 2 :(得分:0)
尝试一下
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