我很确定自己已经把自己画成了一个角落而我无法解决问题。
Users表和OrderHistories表都有超过100万条记录:
SELECT
u.Id ,
u.Email AS EmailAddress ,
c.Address_Address1 AS "Address 1" ,
(
SELECT
COUNT(*)
FROM
dbo.OrderHistories oh
WHERE
oh.UserId = u.UserName
) AS NumberOfOrders ,
Carts.SubtotalAmount AS CartTotal ,
(
SELECT
MAX(oh.CreateDate)
FROM
dbo.OrderHistories AS oh
WHERE
oh.UserId = u.Id
) AS LastOrderDate ,
(
SELECT
LastOrders.SubtotalAmount AS LastOrderSubtotal
FROM
(
SELECT
UserId ,
CreateDate ,
SubtotalAmount ,
MAX(CreateDate) OVER ( PARTITION BY UserId ) MyLastOrderDate
FROM
Users u
INNER JOIN dbo.OrderHistories oh
ON u.Id = oh.UserId
) AS LastOrders
WHERE
LastOrders.MyLastOrderDate = LastOrders.CreateDate
AND LastOrders.UserId = u.Id
) AS LastOrderSubtotal
FROM
Users u
INNER JOIN Customers AS c
ON u.Id = c.Id
LEFT JOIN dbo.Carts
ON c.Id = Carts.CustomerId
这个特殊的子查询是我当前的问题(非常低效),但我没有足够的经验来理解为什么,或者我应该如何做到(我无法从这里到达那里!) :
(
SELECT
LastOrders.SubtotalAmount AS LastOrderSubtotal
FROM
(
SELECT
UserId ,
CreateDate ,
SubtotalAmount ,
MAX(CreateDate) OVER ( PARTITION BY UserId ) MyLastOrderDate
FROM
Users u
INNER JOIN dbo.OrderHistories oh
ON u.Id = oh.UserId
) AS LastOrders
WHERE
LastOrders.MyLastOrderDate = LastOrders.CreateDate
AND LastOrders.UserId = u.Id
) AS LastOrderSubtotal
任何人都在想我是多么可怕,然后直接进入建议的改进?
答案 0 :(得分:1)
只需查看您的查询,您就可以使用cross apply()
进行简化,如下所示:
select
u.Id
, EmailAddress = u.Email
, [Address 1] = c.Address_Address1
, CartTotal = Carts.SubtotalAmount
, NumberOfOrders = oh.NumberOfOrders
, LastOrderDate = oh.CreateDate
, LastOrderSubtotal = oh.SubtotalAmount
from Users u
inner join Customers AS c
on u.Id = c.Id
left join dbo.Carts
on c.Id = Carts.CustomerId
cross apply (
select top 1
i.CreateDate
, i.SubtotalAmount
, NumberOfOrders = count(*) over (partition by i.UserId)
from dbo.OrderHistories i
where i.UserId = u.Id
order by i.CreateDate desc
) as oh
如果您想要的行可能没有OrderHistory
,请切换为outer apply()
。
参考: