同じソースから異なる期間の集計データを比較する必要がある状況によく直面します。同じデータセットからの異なる期間の合計に加算する
私は通常、それをこのように扱う:
SELECT
COALESCE(SalesThisYear.StoreId, SalesLastYear.StoreId) StoreId
, SalesThisYear.Sum_Revenue RevenueThisYear
, SalesLastYear.Sum_Revenue RevenueLastYear
FROM
(
SELECT StoreId, SUM(Revenue) Sum_Revenue
FROM Sales
WHERE Date BETWEEN '2017-09-01' AND '2017-09-30'
GROUP BY StoreId
) SalesThisYear
FULL JOIN (
SELECT StoreId, SUM(Revenue) Sum_Revenue
FROM Sales
WHERE Date BETWEEN '2016-09-01' AND '2016-09-30'
GROUP BY StoreId
) SalesLastYear
ON (SalesLastYear.StoreId = SalesThisYear.StoreId)
-- execution time 337 ms
それが二回表を訪れるので、それは私の意見では非常にエレガントではありませんが、それは動作します。同じことを達成するために
別の同様の方法は次のとおりです。
SELECT
Sales.StoreId
, SUM(CASE YEAR(Date) WHEN 2017 THEN Revenue ELSE 0 END) RevenueThisYear
, SUM(CASE YEAR(Date) WHEN 2016 THEN Revenue ELSE 0 END) RevenueLastYear
FROM
Sales
WHERE
Date BETWEEN '2017-09-01' AND '2017-09-30'
or Date BETWEEN '2016-09-01' AND '2016-09-30'
GROUP BY
StoreId
-- execution time 548 ms
どちらのソリューションは、私のデータセット(選択された期間中に1929419行、その場所のすべてのインデックス)、最初の少し上のほぼ同じを行い、より良い時間で。また、期間を増やしても問題ありません。最初のデータは常にデータセットの方が優れています。
これは単なる例ですが、2つ以上のインターバルを含み、ロジック(たとえば、月/日の代わりにisoweek /曜日を比較したり、異なる店舗を比較するなど)を含む場合もあります。
私はすでに同じことを達成するためのいくつかの方法を考え出しましたが、同じことを達成するための巧妙な方法があるかどうかは疑問でした。多分もっとクリーンなソリューションかもしれません。あるいは大きなデータセット(TB以上)に適しています。
たとえば、大きなデータセットの場合、2つ目のリソースがリソースを集中的に使用しないとします。これは、テーブルに対して1回のインデックススキャンを実行するためです。一方、最初のスキャンでは、2つの索引スキャンと1つのマージが必要です。テーブルが大きすぎてメモリに収まらない場合はどうなりますか?あるいは、最初の方が常に良いですか?
これはまさに私のポイントはありませんでしたが、あなたの推薦は理にかなって、私は、私はなるだろう改善について興味がありました。残念ながら、改善はありませんでした。クエリの平均実行時間は597ミリ秒でした。 –
私のテーブルは日付をVARCHAR形式でYYYYMMDDの形式で格納するので、YEAR(日付)は実際にはLEFT(日付、4)です。ただし、スカラー関数でもあります。 –
大きなデータセットに対するパフォーマンス上の懸念についてどう思いますか?マージ操作はリソースキラーだと思いますか? –