SQL-Server 2005 を使用して、ASP.NET 4.0 の小さな Web アプリケーション用に作成したこのクエリを改善したいと考えています。このアプリケーションにより、ユーザーは製品 ID で検索し、次の情報を返すことができます。
- 最高購入価格 + 最新の購入日 @ この価格
- 最低購入価格 + 最新の購入日 @ この価格
- 最近の購入価格 + 日付
- 平均購入価格 (オプション、これによりアプリの有用性が向上するのではないかと考えました)
Products テーブルの構造は次のとおりです (関連する列のみを含めています。これは既に運用されている DB であり、これらは非 pk 列です)
- product_id (nvarchar(20))
- 価格 (10 進数 (19,2))
- pDate (日時)
これまでのクエリを書き留める前に、複数のクエリを使用してこの情報を簡単に取得できると言いたいだけなので、これがベスト プラクティスである場合は、クエリの改善を無視しますが、必要なクエリの数を最小限に抑えることを目指していました。必要なすべての情報を取得します。
私がこれまでに持っているもの: (注: 価格 = 0 の行があるため、MIN 価格を探して一番下の行を無視しました)
SELECT price, MAX(pDate)
FROM Products
WHERE product_id = @product_id AND
(price = (SELECT MAX(price)
FROM Products
WHERE product_id =@product_id) OR
price = (SELECT MIN(price)
FROM Products
WHERE product_id = @product_id AND price > 0))
GROUP BY price
これで 2 行が返されます。
- 最初 = 最低価格 + 日付
- 2 行目 = 高値 + 日付
理想的には、ASP での情報の表示が簡単になるため、可能であれば上記の必要な情報をすべて含む 1 行をクエリで返すようにすることです。先に述べたように、複数のクエリがアプローチである場合、ここで複雑なクエリを書き直す必要はありません。
編集
ここにいくつかのサンプルデータがあります
必要なクエリ結果: (Excel で入力したので形式は無視してください)
Ken Benson のおかげで使用するクエリは次のとおりです。
SELECT TOP 1 prod.product_id,
minp.price AS minprice, minp.pDate as minlastdate,
maxp.price AS maxprice, maxp.pDate as maxlastdate,
ag.price AS averageprice
FROM products AS prod
LEFT JOIN (SELECT lmd.product_id,max(lmd.pDate) as pDate,mn.price FROM products as lmd INNER JOIN
(SELECT product_id, min(price) AS price from products WHERE price > 0 group by product_id) as mn ON lmd.product_id=mn.product_id AND lmd.price=mn.price
group by lmd.product_id,mn.price ) AS minp ON minp.product_id=prod.product_id
LEFT JOIN (SELECT lxd.product_id,max(lxd.pDate) as pDate,mx.price FROM products as lxd INNER JOIN
(SELECT product_id, max(price) AS price from products group by product_id) as mx ON lxd.product_id=mx.product_id AND lxd.price=mx.price
group by lxd.product_id,mx.price ) AS maxp ON maxp.product_id=prod.product_id
LEFT JOIN (SELECT product_id,avg(price) as price FROM products WHERE price > 0 GROUP BY product_id) AS ag ON ag.product_id=prod.product_id
WHERE prod.product_id=@product_id