いずれにしても、それは在庫あたりの行数の増加に役立ちます(実際のquoteid
の値は実際には役に立ちません)。 (この表の)のキャプチャは最も簡単です。(営業日のみ、週末/休日を無視するなど)何かが必要な場合は、より関与します。おそらくカレンダーファイルが必要です。 [stockid
、createdate
]以上のインデックスがまだ存在しない場合は、そのインデックスを使用します。
提供されたデータから、以下の結果得
WITH StockRow AS (SELECT stockId, closePrice, createdDate,
ROW_NUMBER() OVER(PARTITION BY stockId
ORDER BY createdDate) rn
FROM Quote),
RunGroup AS (SELECT Base.stockId, Base.createdDate,
MAX(Restart.rn) OVER(PARTITION BY Base.stockId
ORDER BY Base.createdDate) groupingId
FROM StockRow Base
LEFT JOIN StockRow Restart
ON Restart.stockId = Base.stockId
AND Restart.rn = Base.rn - 1
AND Restart.closePrice > Base.closePrice)
SELECT stockId,
COUNT(*) AS consecutiveCount,
MIN(createdDate) AS startDate, MAX(createdDate) AS endDate
FROM RunGroup
GROUP BY stockId, groupingId
HAVING COUNT(*) >= 3
ORDER BY stockId, startDate
:
Increasing_Run
stockId consecutiveCount startDate endDate
===================================================
1 5 2012-01-01 2012-01-05
2 4 2012-01-01 2012-01-04
3 3 2012-01-02 2012-01-04
SQL Fiddle Example
を(フィドルも複数の実行のための例があります)
この分析は、すべてのギャップを無視し、すべての実行に正しく一致します(次回の正の実行が開始されたとき)。
ここでは何が起こっているのですか?
StockRow AS (SELECT stockId, closePrice, createdDate,
ROW_NUMBER() OVER(PARTITION BY stockId
ORDER BY createdDate) rn
FROM Quote)
このCTEは1つの目的のために使用されている:我々は、次/前の行を見つけるための方法を必要とするので、最初に我々は(日付の)ために、各列に番号を付けます...
RunGroup AS (SELECT Base.stockId, Base.createdDate,
MAX(Restart.rn) OVER(PARTITION BY Base.stockId
ORDER BY Base.createdDate) groupingId
FROM StockRow Base
LEFT JOIN StockRow Restart
ON Restart.stockId = Base.stockId
AND Restart.rn = Base.rn - 1
AND Restart.closePrice > Base.closePrice)
...インデックスに基づいて結合します。もしあなたがLAG()
/LEAD()
を持っているものに終わるなら、それらを代わりに使うことは、ほぼ確実に良い選択です。ここでは重要なことが1つあります。一致するのは、行がの順序外の場合です((前の行よりも小さい)。それ以外の場合、値はnull
(LAG(), you'd need to use something like
の場合はそれ以降にこれを取り除くことになります)になります。あなたはこのようになります一時的なセットを取得:
B.rn B.closePrice B.createdDate R.rn R.closePrice R.createdDate groupingId
1 15 2012-01-01 - - - -
2 13 2012-01-02 1 15 2012-01-01 1
3 17 2012-01-03 - - - 1
4 18 2012-01-04 - - - 1
5 10 2012-01-05 4 18 2012-01-04 4
を...だから、以前は「現在」の行よりも大きかっただけRestart
の値があります。ウィンドウ関数内のMAX()
の使用は、これまでに見た最大の値に使用されています... null
が最も小さいため、別の不一致が発生するまで(他の値を与える) 。この時点で、最終的な集計に備えて、gaps-and-islandsというクエリの中間結果が得られます。
SELECT stockId,
COUNT(*) AS consecutiveCount,
MIN(createdDate) AS startDate, MAX(createdDate) AS endDate
FROM RunGroup
GROUP BY stockId, groupingId
HAVING COUNT(*) >= 3
ORDER BY stockId, startDate
クエリの最後の部分は、実行の開始日と終了日を取得し、それらの日付の間のエントリ数をカウントしています。日付計算にもっと複雑なものがあった場合は、おそらくこの時点で発生する必要があります。 GROUP BY
は、のいくつかの正当なインスタンスのうちの1つを示しています。これは、SELECT
句の列を含むではありません。 HAVING
句は、「短すぎる」実行を排除するために使用されます。
あなたの最小長の連続的な増加は、一日よりも大きかったらどうしますか?あるいは、何とかその減少によって相殺されましたか?そして、私はそれについてのデータがあれば、あなたは複数の実行を見たいと思っています。 –
週末のようにデータに隙間がありますか?そこで何をする必要がありますか? –
私は連続的な増加のための規則を持っていません、それは前日よりも大きくなければなりません。はい、私は複数の実行を探しています。私はこの質問を過去3ヶ月、6ヶ月のデータにわたって実行しているか、それ以上であるかもしれません。データにギャップがあります、私たちは前の日のレコードを取得するために主キーの列を使用することができます –