無論如何,它有助於將它放在逐行增加的行中(實際的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被用於一個目的:我們需要一種方法來尋找下一個/前行,所以首先我們爲了(日期)編號每行...
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()
,那麼使用它們幾乎肯定會是更好的選擇。這裏有一個重要的事情 - 匹配只有當行是亂序(小於前一行)。否則,該值最終爲null
(隨後LAG(), you'd need to use something like
CASE`將其取消)。你得到一個臨時組看起來是這樣的:
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
顯示了而不是的少數幾個合法實例之一,其中包括SELECT
子句中的一列。 HAVING
子句用於消除「太短」的運行。
你想要你的最小長度連續增加是多少 - 只比一天多一點?或者以某種方式抵消其減少?我假設你想看到多次運行,如果有數據的話。 – 2012-04-27 16:49:27
數據中是否存在任何差距 - 比如週末 - 以及需要做些什麼? – 2012-04-27 16:56:01
我沒有連續增加的規則,它只需要比前一天更大。是的,我正在尋找多次運行。我將針對過去3個月,6個月的數據運行此查詢,或者可能不止於此。數據中會有空白,我們可以使用主鍵列取得前一天的記錄 – 2012-04-27 17:33:55