0

私は 4 つのテーブルを持つ小さなデータベースを持っています: Customer - Order - OrderLine - Product、私はクエリで少し遊んでいて、最も高価な注文を持つ人々の名前を取得しようとしています。

いろいろ試した後、すべての注文の価格を表示する次のクエリを思いつきました。

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 = 1rnk <= n

于 2012-05-17T07:10:11.087 に答える