我有一张表,例如这个数据
ID |start_date |end_date |amount
---|------------|-----------|-------
a1 |2013-12-01 |2014-03-31 |100
我想要一个分割日期的查询,这样我就可以像这样分出一年中的金额:
ID |org_start_date |org_end_date |new_start_date |new_end_date |amount
---|----------------|---------------|----------------|----------------|-------
a1 |2013-12-01 |2014-03-31 |2013-12-01 |2013-12-31 |25
a1 |2013-12-01 |2014-03-31 |2014-01-01 |2014-03-31 |75
2013年的25个是因为2013年有一个月和75个,因为这有3个月
有没有办法在T-SQL中执行此操作?
提前谢谢!答案 0 :(得分:2)
以下是使用数字表的解决方案:
DECLARE @STARTYR INT = (SELECT MIN(YEAR([Start Date])) FROM Table1)
DECLARE @ENDYR INT = (SELECT MAX(YEAR([End Date])) FROM Table1)
SELECT [Id]
, @STARTYR + Number AS [Year]
, CASE WHEN YEAR([Start Date]) < @STARTYR + Number
THEN DATEADD(YEAR, @STARTYR - 1900 + Number,0)
ELSE [Start Date] END AS [Start]
, CASE WHEN YEAR([End Date]) > @STARTYR + Number
THEN DATEADD(YEAR, @STARTYR - 1900 + Number + 1,0)
ELSE [End Date] END AS [End]
, DATEDIFF(MONTH,CASE WHEN YEAR([Start Date]) < @STARTYR + Number
THEN DATEADD(YEAR, @STARTYR - 1900 + Number,0)
ELSE [Start Date] END
,CASE WHEN YEAR([End Date]) > @STARTYR + Number
THEN DATEADD(YEAR, @STARTYR - 1900 + Number + 1,0)
ELSE DATEADD(MONTH,DATEDIFF(MONTH,0,DATEADD(MONTH,1,[End Date])),0) END) AS [Months]
, DATEDIFF(MONTH,[Start Date],[End Date]) + 1 [Total Months]
, ([Amount] / (DATEDIFF(MONTH,[Start Date],[End Date]) + 1))
*
DATEDIFF(MONTH,CASE WHEN YEAR([Start Date]) < @STARTYR + Number
THEN DATEADD(YEAR, @STARTYR - 1900 + Number,0)
ELSE [Start Date] END
,CASE WHEN YEAR([End Date]) > @STARTYR + Number
THEN DATEADD(YEAR, @STARTYR - 1900 + Number + 1,0)
ELSE DATEADD(MONTH,DATEDIFF(MONTH,0,DATEADD(MONTH,1,[End Date])),0) END) AS [Proportion]
FROM Numbers
LEFT JOIN Table1 ON YEAR([Start Date]) <= @STARTYR + Number
AND YEAR([End Date]) >= @STARTYR + Number
WHERE Number <= @ENDYR - @STARTYR
答案 1 :(得分:2)
使用spt_values
表创建日历表,然后加入您的表格,将日期范围拆分为您想要的任何部分。
如果按年份划分并按月划分金额,您可以:
with dates as
(
select number,DATEADD(day,number,'20130101') as dt
from master..spt_values
where number between 0 and 1000 AND TYPE='P'
)
select
m.start_date as org_start_date,
m.end_date as org_end_date,
min(d.dt) as new_start_date,
max(d.dt) as new_end_date,
m.amount*count(distinct month(d.dt))/(datediff(month,m.start_date,m.end_date)+1) as amount
from
MonthSplit m
join
dates d
on
d.dt between m.start_date and m.end_date
group by
m.start_date, m.end_date, year(d.dt),m.amount
答案 2 :(得分:0)
这与这个问题非常相似:
<强> Split date range into one row per month in sql server 强>
虽然您按年度进行分组,但根据该答案,您可以通过将MIN
,MAX
添加到日期值并按{{1}分组来修改它以执行您想要的操作}:
架构设置:
YEAR()
递归CTE按年份分组:
CREATE TABLE MonthSplit
([ID] varchar(2), [start_date] datetime, [end_date] datetime, [amount] int)
;
INSERT INTO MonthSplit
([ID], [start_date], [end_date], [amount])
VALUES
('a1', '2013-12-01 00:00:00', '2014-03-31 00:00:00', 100),
('a2', '2013-10-01 00:00:00', '2015-05-01 00:00:00', 400)
;
<强> Results 强>:
WITH cte AS
(SELECT ID
, start_date
, end_date
, start_date AS from_date
, DATEADD(day, day(start_date)* -1 + 1, start_date) AS first_of_month
FROM MonthSplit
UNION ALL
SELECT ID
, start_date
, end_date
, DATEADD(month,1,first_of_month)
, DATEADD(month,1,first_of_month)
FROM cte
WHERE DATEADD(month,1,from_date) < end_date
)
SELECT ID as ID,
min(start_date) as org_start_date,
min(end_date) as org_end_date,
min(from_date) AS new_start_date,
CASE when max(end_date) < DATEADD(month,1,max(first_of_month)) THEN
max(end_date)
ELSE
DATEADD(day, -1, DATEADD(month,1,max(first_of_month)))
END AS new_end_date
FROM cte
group by year(from_date), ID
答案 3 :(得分:0)
我没有为您准备好现成的SQL,只是想解决这个问题。如果您对SQL有一些经验,那么很难用SQL表达它。
您可以通过为开始日期和结束日期之间的月份定义参考表来完成此操作:
ID | month | year | month start | month end | count |
-----------------------------------------------------------------------------
1001 | dec-2013 | 2013 | 1-12-2013 | 31-12-2013 | 1 |
1001 | jan-2014 | 2014 | 1-1-2014 | 31-1-2014 | 1 |
1001 | feb-2014 | 2014 | 1-2-2014 | 28-2-2014 | 1 |
1001 | mar-2014 | 2014 | 1-3-2014 | 31-3-2014 | 1 |
也许你的DWH中已经有了这样的时间参考表。
当您使用包含每行的开始日期和结束日期的记录加入(使用之间声明)您的表时,使用此参考表,您将从1行拆分到包含的行数范围正确。计数栏将帮助您通过以后的一年中的分组来获得每年的分配比率(例如:2013年的1/4和2014年的3/4)。您必须将该比率应用于字段&#39; amount&#39;你想要分手。