次のクエリがあるとします。
SELECT
p.ProductName,
CASE
WHEN EXISTS(SELECT 1 FROM Product WHERE ProductSuperID = p.ProductSuperID AND HasImage = 1)
THEN
1
ELSE
0
END
AS HasImage,
(SELECT Sum(StockBalance) FROM Product WHERE ProductSuperID = p.ProductSuperID) AS StockBalance,
CASE
WHEN EXISTS(SELECT 1 FROM Product WHERE ProductSuperID = p.ProductSuperID AND Price IS NULL)
AND EXISTS(SELECT 1 FROM Product WHERE ProductSuperID = p.ProductSuperID AND DiscountPrice IS NULL)
THEN
0
ELSE
1
END
AS HasPrice
FROM ProductSuper p
-- SCHEMA
CREATE TABLE ProductSuper
(
ProductSuperID int,
ProductName varchar(255)
)
CREATE TABLE Product
(
ProdID int,
ProductSuperID int,
HasImage bit,
StockBalance int,
Price decimal(10,2),
DiscountPrice decimal(10,2)
)
INSERT INTO ProductSuper
(ProductSuperID, ProductName)
VALUES
(1, 'Product 1'),
(2, 'Product 2')
INSERT INTO Product
(ProductSuperID, HasImage, StockBalance, Price, DiscountPrice)
VALUES
(1, 0, 10, 10.00, 9.00),
(1, 0, 0, 10.00, 9.00),
(2, 0, 10, 10.00, 9.00),
(2, 0, 2, 10.00, 9.00),
(2, 1, 5, 10.00, 9.00)
コードの重複を避けるためにJOIN
またはCROSS APPLY
を使用するように書き直す方法を学びたいです。 JOINベースのバージョン(およびAPPLYを使用したバージョン)を作成しようとしましたが、ProductSuper
テーブルの各行について複数の結果が返されましたが、1行しか必要ありません。
つまり、期待される結果:
+-------------+-----+-----+-----+
| Product 1 | 0 | 10 | 1 |
+-------------+-----+-----+-----+
| Product 2 | 1 | 17 | 1 |
+-------------+-----+-----+-----+
(この特定のコードでは、サブクエリが高速であるため、書き換えによるメリットはほとんどないことを認識しています。しかし、これは単なる例にすぎません。)
ありがとう。
私はおそらくこのクエリを以下のように構成します
WITH ProductDetails
AS (SELECT ProductSuperID,
HasImage = MAX(CASE WHEN HasImage = 1 THEN 1 ELSE 0 END),
StockBalance = Sum(StockBalance),
HasPrice = CASE WHEN COUNT(*) = COUNT(Price) AND COUNT(*) = COUNT(DiscountPrice) THEN 1 ELSE 0 END
FROM Product
GROUP BY ProductSuperID)
SELECT p.ProductName,
HasImage = ISNULL(pd.HasImage,0),
pd.StockBalance,
HasPrice = ISNULL(pd.HasPrice,0)
FROM ProductSuper p
LEFT JOIN ProductDetails pd
ON p.ProductSuperID= pd.ProductSuperID;
なので CROSS APPLY
このように書くことができます
SELECT ps.ProductName,
pd.HasImage,
pd.StockBalance,
pd.HasPrice
FROM ProductSuper ps
CROSS APPLY (SELECT HasImage = MAX(CASE WHEN HasImage = 1 THEN 1 ELSE 0 END),
StockBalance = Sum(StockBalance),
HasPrice = CASE WHEN COUNT(*) = COUNT(Price) AND COUNT(*) = COUNT(DiscountPrice) THEN 1 ELSE 0 END
FROM Product p
WHERE p.ProductSuperID= ps.ProductSuperID) pd