无论如何,将它放在增加每张纸的行数方面
quoteid是有帮助的(实际值在这里并不是真的有帮助)。 捕获 的天数(在此表中)是最简单的-
如果您想要其他内容(例如仅工作日,忽略周末/节假日等),则它会涉及更多;您可能需要一个日历文件。如果您还没有索引,您将要在[
stockid,
createdate]上建立索引。
WITH StockRow AS (SELECt stockId, closePrice, createdDate, ROW_NUMBER() OVER(PARTITION BY stockIdORDER 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 endDateFROM RunGroupGROUP BY stockId, groupingIdHAVINg COUNT(*) >= 3ORDER BY stockId, startDate
从提供的数据中得出以下结果:
Increasing_RunstockId consecutiveCount startDate endDate===================================================1 5 2012-01-01 2012-01-052 4 2012-01-01 2012-01-043 3 2012-01-02 2012-01-04
[SQL Fiddle Example](http://sqlfiddle.com/#!6/b1e78/4/0)
(提琴还有一个多次运行的示例)
该分析将忽略所有差距,正确匹配所有运行(下次开始运行正运行时)。
那么这是怎么回事?
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(),您需要使用类似
CASEafter
after的东西来实现此目的)。您得到一个看起来像这样的临时集:
B.rn B.closePrice B.createdDate R.rn R.closePrice R.createdDate groupingId1 15 2012-01-01 - - - -2 13 2012-01-02 1 15 2012-01-01 13 17 2012-01-03 - - - 14 18 2012-01-04 - - - 15 10 2012-01-05 4 18 2012-01-04 4
…因此,
Restart仅当上一个大于“当前”行时才有值。
MAX()到目前为止,在窗口函数中使用的值已达到最大值……这
null是最低值,它会导致所有其他行的行索引都保留下来,直到发生另一个不匹配(给出新值)为止。至此,我们基本上有了间隔和孤岛查询的中间结果,可以进行最终汇总了。
SELECt stockId, COUNT(*) AS consecutiveCount, MIN(createdDate) AS startDate, MAX(createdDate) AS endDateFROM RunGroupGROUP BY stockId, groupingIdHAVINg COUNT(*) >= 3ORDER BY stockId, startDate
查询的最后一部分是获取运行的开始日期和结束日期,并计算这些日期之间的条目数。如果日期计算有些复杂,则可能需要在此时进行。在
GROUPBY被示出的几个合法实例中的一个 不 包括在列
SELECT子句。该
HAVINg子句用于消除“过短”的运行。



