0

我有一个包含 4 个表的小型数据库:客户 - 订单 - 订单线 - 产品,我正在玩一些查询,并试图获取订单最昂贵的人的姓名。

在玩了一些之后,我想出了以下查询,它显示了所有订单的价格:

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

这将检索客户列表,其中他们的订单价格等于最昂贵订单的价格。这正好检索到我想要的东西,但感觉非常多余。

我应该如何开始提高效率(如果可能)?

4

2 回答 2

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

排名前 1 的订单

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)

或者,如果您想要客户姓氏的最大值。你可以这样做:

;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
于 2012-05-16T07:29:08.733 回答
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()or 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

于 2012-05-17T07:10:11.087 回答