FGITWと競合するつもりはありませんが、このクエリについて何か言わなければなりません...
空白を追加すると、私の言いたいことがわかると思います。
SELECT SUM( (COUNT(BookingID) * CategoryPrice) ) AS TotalAmount
FROM Booking
, Production
WHERE Booking.PerformanceID IN ( SELECT PerformanceID
FROM Performance
WHERE PerformanceID = '1')
AND Production.ProductionID IN ( SELECT ProductionID FROM Performance
WHERE PerformanceID = '1')
GROUP BY BookingID, CategoryPrice
UNION ALL
SELECT SUM( (COUNT(BookingID) * CategoryPrice)) AS TotalAmount
FROM Booking
, Production
WHERE Booking.PerformanceID IN ( SELECT PerformanceID
FROM Performance
WHERE PerformanceID = '2')
AND Production.ProductionID IN ( SELECT ProductionID
FROM Performance
WHERE PerformanceID = '2')
GROUP BY BookingID, CategoryPrice
クエリを分解すると、 2 つの行が返された唯一の理由は、分析関数とすべての結合です。
- との間でデカルト結合を行っています。これは、それぞれの行数を互いに乗算することを意味します。
booking
production
- あなたの副選択
performance
は、すでに知られている1つの値を返しています。それらを行う理由はまったくありません。
- 暗黙的に数値を文字列に変換し、再び数値に戻しています。
- ここでは、テーブルまたはインデックスを 8 回スキャンしています。
パフォーマンスごとに取得した合計金額が必要なように見えます。この場合、クエリは次のように簡略化できます。
SELECT SUM(bookings * CategoryPrice)
FROM ( SELECT CategoryPrice , count(*) as bookings
FROM Booking b
JOIN performance per
ON p.performanceid = per.performanceid
JOIN Production p
ON p.productionid = per.productionid
WHERE p.performanceid in (1, 2)
GROUP BY CategoryPrice
)
明示的な結合構文に注意してください。これは数十年前から存在しており、物事をより明確にし、間違いを防ぐのに役立ちます。このクエリは、両方のテーブルにインデックスがあると仮定して、booking
の 1つと の 1 つで、2 つの範囲スキャンを実行します。また、それがこのテーブルの主キーであると仮定して、一意のスキャンも実行します。production
performanceid
performance
performanceid
これが何をするかの説明として、ようやくスキーマを正しくすることができました! 2 つのパフォーマンスを選択し1
ます2
。次に、それらの公演に関連するすべての作品と、それらの作品に関連するすべての予約を選択します。含まれているテーブルによっては、これをさらに単純化できる場合がありますcategoryprice
。次に、1 件あたりの予約数を取得し、categoryprice
これらの積を合計して合計値を算出します。
ちょっとしたアドバイスとして、クエリが正しいことを受け入れる前に、クエリから返されると予想される値を理解することを常にお勧めします。最高の人間は間違いを犯す可能性があり、間違いを犯します。返された値が正しくないことがわかるので、それらをキャッチできると役立ちます。
参考文献: