【问题标题】:How to split months between a start date and end date from a table in SQL如何在 SQL 中的表中拆分开始日期和结束日期之间的月份
【发布时间】:2019-06-23 22:39:09
【问题描述】:

我想在 SQL Server 中设置一个存储过程,它根据每种货币的开始和结束日期创建逐月的货币汇率。

以下是我要使用的表格格式:

Table 1 (Input Table)
+------------+------------+------------+
| Start Date |  End Date  |  Currency  |
+------------+------------+------------+
| 01/01/2016 | 30/05/2016 |   EUR      | 
| 01/03/2017 | 31/05/2017 |   BDT      | 
+------------+------------+------------+

从上表中,我希望存储过程给出这样的输出:

Table 2 (Desired result from sql script)
Date        Currency
---------------------
01/01/2016  EUR
01/02/2016  EUR
01/03/2016  EUR
01/04/2016  EUR
01/05/2016  EUR
01/03/2017  BDT
01/04/2017  BDT
01/05/2017  BDT

然后我想加入这两个输出来给出一个像这样的决赛桌:

Final Table (Join on Table 1 and 2) 

Start Date  End Date    Split Date  Currency    Exchange Rate
-------------------------------------------------------------
01/01/2016  30/05/2016  18/01/2016  EUR         x
01/01/2016  30/05/2016  18/02/2016  EUR         z
01/01/2016  30/05/2016  18/03/2016  EUR         h
01/01/2016  30/05/2016  18/04/2016  EUR         g
01/01/2016  30/05/2016  18/05/2016  EUR         a
01/03/2017  31/05/2018  01/03/2017  BDT         b
01/03/2017  31/05/2018  01/04/2017  BDT         c
01/03/2017  31/05/2018  01/05/2017  BDT         f

我在stackoverflow上找到了一些这样的解决方案:

declare @StartDate date = '20170401'
      , @EndDate   date = '20170731';

;with Months as 
(
    select top (datediff(month, @startdate, @enddate) + 1) 
        [Month] = dateadd(month, row_number() over (order by number) -1, @StartDate),
        MonthEnd = dateadd(day,-1,dateadd(month, row_number() over (order by number), @StartDate))   
    from 
        master.dbo.spt_values   
    order by 
        [Month] 
) 
select * from Months;

但是,这仅使用硬编码的开始和结束日期。我希望从输入表中的每一行获取开始日期和结束日期,就像问题开头提到的那样。

【问题讨论】:

  • 请阅读this,了解一些改进问题的技巧。您提供了几个示例数据表,但没有 DDL,也没有说明数据如何从一个表转换到下一个表。
  • 我看不到临时表在最终结果中的使用位置。最终结果似乎是第一个表的开始日期和结束日期之间的每一天。如果需要,您使用 CTE 找到的示例可以轻松使用源表中的日期而不是固定日期,但我认为这不会回答您的基本问题。
  • 另外,您的欧元结束日期早于您的开始日期。
  • 这个问题有很多令人困惑的东西并且没有足够的信息:1>您能否提供您的输入参与表DDL和一些示例数据,然后提供您正在寻找的输出而不是提供你的中间数据是什么样的? 2> 不确定您从哪里获得 ExchangeRate 值。 3> 您的欧元结束日期似乎早于您的开始日期。您能否使用这些详细信息编辑问题?
  • 4> 另外,您能否解释一下为什么您的输出 SplitDate 为每月 18 欧元,相对于其 StartsDate = 18/01/2016,但对于 BDT,它是每月 1 日,即使它是开始日期 = 2017 年 3 月 19 日?

标签: sql sql-server database tsql


【解决方案1】:

我想我已经知道你想要做什么了。这将在一个查询中完成。

首先设置您的测试数据(纠正您的错误,其中 enddate 是

create table xchg(startdate date, enddate date, currency varchar(3))
insert xchg values ('2016-01-18','2016-05-30','EUR')
,('2017-03-19','2017-05-31','BDT')

然后是一个递归查询,找出两个日期之间的每个周年纪念日。不知道您从哪里获得汇率,但您应该可以将其添加到 this 中。

;with splits as
(
    select *, startdate as split from xchg
    union all
    select startdate, enddate, currency, 
        dateadd(m,1,split) 
    from splits
    where dateadd(m,1,split) <= enddate
)
select * from splits order by currency, split

结果是:

startdate   enddate     currency    split
2017-03-19  2017-05-31  BDT         2017-03-19
2017-03-19  2017-05-31  BDT         2017-04-19
2017-03-19  2017-05-31  BDT         2017-05-19
2016-01-18  2016-05-30  EUR         2016-01-18
2016-01-18  2016-05-30  EUR         2016-02-18
2016-01-18  2016-05-30  EUR         2016-03-18
2016-01-18  2016-05-30  EUR         2016-04-18
2016-01-18  2016-05-30  EUR         2016-05-18

【讨论】:

  • 非常感谢。这个对我有用。汇率将来自外部来源。我也根据您的反馈纠正了错别字:)
猜你喜欢
  • 2013-02-10
  • 1970-01-01
  • 2020-12-17
  • 1970-01-01
  • 2020-10-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-01-09
相关资源
最近更新 更多