我有一个包含4个表的小型数据库:客户 - 订单 - OrderLine - 产品,我正在玩一些查询,并试图获取最昂贵订单的人的名字。
经过一些游戏后,我想出了以下查询,其中显示了所有订单的价格:
SELECT SUM(OrderLine.Amount * Product.Price) AS OrderLinePrice, Orders.Id, Customer.Lastname
FROM OrderLine, Product, Orders, Customer
WHERE OrderLine.ProductId = Product.Id
AND Orders.Id = OrderLine.OrderId
AND Customer.Id = Orders.CustomerId
GROUP BY Orders.Id, Customer.Lastname
ORDER BY OrderLinePrice DESC
现在我在概念上需要做的,或者我认为我需要做的是,应用MAX()来只选择最高的OrderLinePrice,但是我没有成功,因为SQL Server抱怨无法执行聚合函数包含聚合的表达式......
===============更新:
目前我的查询如下:
SELECT t.CustomerLastName
FROM (
SELECT SUM(OrderLine.Amount * Product.Price) AS OrderLinePrice, Orders.Id, Customer.Lastname AS CustomerLastName
FROM OrderLine, Product, Orders, Customer
WHERE OrderLine.ProductId = Product.Id
AND Orders.Id = OrderLine.OrderId
AND Customer.Id = Orders.CustomerId
GROUP BY Orders.Id, Customer.Lastname
) AS t
WHERE t.OrderLinePrice =
(
SELECT MAX(s.OrderLinePrice) AS MaxOrderPrice
FROM (
SELECT SUM(OrderLine.Amount * Product.Price) AS OrderLinePrice, Orders.Id, Customer.Lastname AS CustomerLastName
FROM OrderLine, Product, Orders, Customer
WHERE OrderLine.ProductId = Product.Id
AND Orders.Id = OrderLine.OrderId
AND Customer.Id = Orders.CustomerId
GROUP BY Orders.Id, Customer.Lastname
) AS s
)
ORDER BY CustomerLastName
这将检索客户列表,其订单价格等于最昂贵订单的价格。这确切地检索了我想要的东西,但感觉非常多余。
我应该如何开始提高效率(如果可能的话)?
答案 0 :(得分:2)
您可以通过多种方式完成此操作。以下是一些建议:
<强> CTE 强>
;WITH CTE
AS
(
SELECT SUM(OrderLine.Amount * Product.Price) AS OrderLinePrice,
Orders.Id, Customer.Lastname
FROM OrderLine, Product, Orders, Customer
WHERE OrderLine.ProductId = Product.Id
AND Orders.Id = OrderLine.OrderId
AND Customer.Id = Orders.CustomerId
GROUP BY Orders.Id, Customer.Lastname
)
SELECT
MAX(OrderLinePrice) AS MaxorderPrice
FROM
CTE
子查询,最大
SELECT
MAX(t.OrderLinePrice) AS MaxorderPrice
FROM
(
SELECT SUM(OrderLine.Amount * Product.Price) AS OrderLinePrice,
Orders.Id, Customer.Lastname
FROM OrderLine, Product, Orders, Customer
WHERE OrderLine.ProductId = Product.Id
AND Orders.Id = OrderLine.OrderId
AND Customer.Id = Orders.CustomerId
GROUP BY Orders.Id, Customer.Lastname
) AS t
按订单排名第一
SELECT TOP 1
t.Amount
FROM
(
SELECT SUM(OrderLine.Amount * Product.Price) AS OrderLinePrice,
Orders.Id, Customer.Lastname
FROM OrderLine, Product, Orders, Customer
WHERE OrderLine.ProductId = Product.Id
AND Orders.Id = OrderLine.OrderId
AND Customer.Id = Orders.CustomerId
GROUP BY Orders.Id, Customer.Lastname
) AS t
ORDER BY t.OrderLinePrice DESC
修改强>
也许是这样的:
;WITH CTE
AS
(
SELECT SUM(OrderLine.Amount * Product.Price) AS OrderLinePrice,
Orders.Id, Customer.Lastname
FROM OrderLine, Product, Orders, Customer
WHERE OrderLine.ProductId = Product.Id
AND Orders.Id = OrderLine.OrderId
AND Customer.Id = Orders.CustomerId
GROUP BY Orders.Id, Customer.Lastname
)
SELECT
*
FROM
CTE
WHERE
CTE.OrderLinePrice=(SELECT MAX(CTE2.OrderLinePrice) FROM CTE AS CTE2)
或者,如果您想要max by customer姓氏。你可以这样做:
;WITH CTE
AS
(
SELECT SUM(OrderLine.Amount * Product.Price) AS OrderLinePrice,
Orders.Id, Customer.Lastname
FROM OrderLine, Product, Orders, Customer
WHERE OrderLine.ProductId = Product.Id
AND Orders.Id = OrderLine.OrderId
AND Customer.Id = Orders.CustomerId
GROUP BY Orders.Id, Customer.Lastname
)
SELECT
MAX(OrderLinePrice) AS MaxPrice,
Lastname
FROM
CTE
GROUP BY
CTE.Lastname
答案 1 :(得分:1)
首先,您是否考虑过使用显式连接?它可能只是一个品味问题,但也许您会发现显式连接的查询比隐式连接(或“逗号”连接)更清晰,就像在您的示例中一样。
至于问题,您可以使用TOP (1) WITH TIES
,如下所示:
WITH ranked AS (
SELECT
SUM(ol.Amount * p.Price) AS OrderLinePrice,
o.Id,
c.Lastname AS CustomerLastName
FROM OrderLine ol
INNER JOIN Product p ON p.Id = ol.ProductId
INNER JOIN Orders o ON o.Id = ol.OrderId
INNER JOIN Customer c ON c.Id = o.CustomerId
GROUP BY Orders.Id, Customer.Lastname
)
SELECT *
FROM (
SELECT TOP (1) WITH TIES CustomerLastName
FROM ranked
ORDER BY OrderLinePrice DESC
) s
ORDER BY CustomerLastName
或者您可以使用RANK()
或DENSE_RANK()
,如下所示:
WITH ranked AS (
SELECT
SUM(ol.Amount * p.Price) AS OrderLinePrice,
o.Id,
c.Lastname AS CustomerLastName,
RANK() OVER (ORDER BY SUM(ol.Amount * p.Price) DESC) AS rnk
FROM OrderLine ol
INNER JOIN Product p ON p.Id = ol.ProductId
INNER JOIN Orders o ON o.Id = ol.OrderId
INNER JOIN Customer c ON c.Id = o.CustomerId
GROUP BY Orders.Id, Customer.Lastname
)
SELECT CustomerLastName
FROM ranked
WHERE rnk = 1
ORDER BY CustomerLastName
如果您只对最高价格感兴趣,RANK()
就足够了,但如果您希望客户获得最高 n
总计,请使用DENSE_RANK()
相反,将条件从rnk = 1
更改为rnk <= n
。