样本数据:
Date Price 1-Jan 3.2 2-Jan 3.2 3-Jan 3.2 4-Jan 3.2 5-Jan 3.2 6-Jan 3.2 7-Jan 3.2 8-Jan 3.2 9-Jan 3.5 10-Jan 3.5 11-Jan 3.5 12-Jan 3.5 13-Jan 3.5 14-Jan 4.2 15-Jan 4.2 16-Jan 4.2 17-Jan 3.2 18-Jan 3.2 19-Jan 3.2 20-Jan 3.2 21-Jan 3.2 22-Jan 3 23-Jan 3 24-Jan 3 25-Jan 3 26-Jan 3 27-Jan 3 28-Jan 3 29-Jan 3.5 30-Jan 3.5 31-Jan 3.5
期望的结果:
Price Date Range 3.2 1-8 3.5 9-13 4.2 14-16 3.2 17-22 3 22-28 3.5 29-31
解决方法
我不认为任何其他答案是正确的.
> GROUP BY不起作用
>使用ROW_NUMBER()强制数据进入物理记录文件系统结构,然后将其作为物理记录处理.以巨大的性能成本.当然,为了编写这样的代码,它会迫使您根据RFS进行思考,而不是用关系术语来思考.
>使用CTE是一样的.迭代数据,尤其是不变的数据.价格略有不同.
>由于不同的原因,游标绝对是错误的. (a)游标需要代码,并且您已请求View(b)游标放弃集合处理引擎,并恢复为逐行处理.同样,不是必需的.如果我的任何团队的开发人员在关系数据库上使用游标或临时表(即不是记录文件系统),我会拍摄它们.
关系解决方案
>您的数据是关系的,逻辑的,两个给定的数据列都是必需的.
>当然,我们必须形成一个View(派生关系),以获得所需的报告,但它包含纯SELECT,这与处理(将其转换为文件,物理,然后处理文件)完全不同;或临时表;或工作表;或CTE;或ROW_Number();等).
>与具有议程的“理论家”的哀叹相反,sql非常好地处理关系数据.而你的数据是关系型的.
因此,维护关系思维模式,数据的关系视图和集合处理心态.可以使用单个SELECT来满足关系数据库上的每个报告要求.没有必要回归到1970年以前的ISAM文件处理方法.
我将假设主键(给出关系行唯一性的列集)是Date,并且基于给定的示例数据,数据类型是DATE.
尝试这个:
CREATE VIEW MyTable_Base_V -- Foundation View AS SELECT Date,Date_Next,Price FROM ( -- Derived Table: project rows with what we need SELECT Date,[Date_Next] = DATEADD( DD,1,O.Date ),Price,[Price_Next] = ( SELECT Price -- NULL if not exists FROM MyTable WHERE Date = DATEADD( DD,O.Date ) ) FROM MyTable MT ) AS X WHERE Price != Price_Next -- exclude unchanging rows GO CREATE VIEW MyTable_V -- Requested View AS SELECT [Date_From] = ( -- Date of the prevIoUs row SELECT MAX( Date_Next ) -- prevIoUs row FROM MyTable_V WHERE Date_Next < MT.Date ),[Date_To] = Date,-- this row Price FROM MyTable_Base_V MT GO SELECT * FROM MyTable_V GO
方法,通用
当然这是一种方法,因此它是通用的,它可以用于根据任何数据变化(这里是价格变化)确定任何数据范围(这里是日期范围)的From_和To_.
在这里,您的日期是连续的,因此Date_Next的确定很简单:将日期增加1天.如果PK正在增加但不是连续的(例如,DateTime或TimeStamp或其他一些键),请将派生表X更改为:
-- Derived Table: project rows with what we need SELECT DateTime,[DateTime_Next] = ( -- first row > this row SELECT TOP 1 DateTime -- NULL if not exists FROM MyTable WHERE DateTime > MT.DateTime ),[Price_Next] = ( -- first row > this row SELECT TOP 1 Price -- NULL if not exists FROM MyTable WHERE DateTime > MT.DateTime ) FROM MyTable MT
请享用.
请随时发表评论,提出问题等.