微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

sql – 日期相同数据集的范围

我正在尝试构建一个SQL查询,它将为我提供具有相同价格的日期的日期范围.如果价格出现中断,我预计会看到新的价格.即使在这个月的某个时间有相同的价格,如果价格发生变化,我希望将其视为具有特定日期范围的两个单独的行.

样本数据:

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

请享用.

请随时发表评论,提出问题等.

原文地址:https://www.jb51.cc/mssql/83422.html

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐