sql server 中两个日期之间的年份以及每个日期在 sql server 中的开始和结束日期

Posted

技术标签:

【中文标题】sql server 中两个日期之间的年份以及每个日期在 sql server 中的开始和结束日期【英文标题】:years between two dates in sql server with starting and end date of each of them in sql server 【发布时间】:2019-09-18 12:22:30 【问题描述】:

我想获取两个日期之间的年份及其开始日期和结束日期。假设如果我输入 startdate 为“07/06/2017”,enddate 输入为“18/09/2019”,我想列出两者之间的年份他们分别的开始和结束日期。请建议我如何实现。

输入表:

BusinessRefId   Period  GoalType                Amount  StartDateUtc    EndDateUtc  Currency
Business B      Year    CommittedTransactionFee 18000   07/06/17 00:00              USD

输出表:

BusinessRefId   Period      GoalType                Amount  StartDateUtc    EndDateUtc  Currency
Business B      2019-2020   CommittedTransactionFee 18000   07/06/2019      07/06/2020  USD
Business B      2018-2019   CommittedTransactionFee 18000   07/06/2018      07/06/2019  USD
Business B      2017-2018   CommittedTransactionFee 18000   07/06/2017      07/06/2018  USD

我需要将日期拆分为月份,即如果 BusinessGoal.Period = 'Month',我需要一个查询来根据 BusinessGoal 表中提到的期间拆分日期,并在输入和输出表中给出“年”和“月”。 输入表(BusinessGoal):

BusinessRefId   Period  GoalType                Amount  StartDateUtc      EndDateUtc         Currency
Business C      Year    CommittedTransactionFee 18000   05/07/19 00:00:00 19/09/19 00:00:00  USD

输出表(BusinessGoal):

BusinessRefId   Period              GoalType                Amount  StartDateUtc         EndDateUtc           Currency
Business C      2019-07 - 2019-08   CommittedTransactionFee 18000   05/07/2019 00:00:00  05/08/2019 00:00:00    USD
Business C      2019-08 - 2019-09   CommittedTransactionFee 18000   05/08/2019 00:00:00  05/09/2019 00:00:00    USD
Business C      2019-09 - 2019-10   CommittedTransactionFee 18000   05/09/2019 00:00:00  05/10/2019 00:00:00    USD

【问题讨论】:

【参考方案1】:

你需要一个数字表,这里我用最简单的一个

select BusinessRefId 
  , cast(ys.y as varchar(4)) + '-' + cast(ys.y + 1 as varchar(4))  Period
  , GoalType, Amount
  , dateadd(year, nmbs.n, tbl.StartDateUtc) StartDateUtc
  , dateadd(year, nmbs.n + 1,tbl.StartDateUtc) EndDateUtc
  , Currency
from 
-- your real table here
(values (1, 'year', 'CommittedTransactionFee', 1800, cast('20160607' as date),  cast (null as date), 'USD')) 
tbl(BusinessRefId, Period, GoalType, Amount, StartDateUtc, EndDateUtc, Currency)
join 
-- table of numbers
(values (0),(1),(2) --,..
 ) nmbs(n)
on dateadd(year, nmbs.n + 1, tbl.StartDateUtc) <= getdate()
cross apply (select Year(tbl.StartDateUtc) + nmbs.n y ) ys

编辑

见fiddle 这是我的查询版本,其中包含更多关于需要哪些行的条件(注意ON 子句中的差异)以及如何计算结束日期。它使用 Soundappan 的 ddl 和数据(扩展),据称这些数据与真实的 ddl 和数据非常接近。 主要思想是相同的,使用数字表。您可能希望在数据库中实例化表以在其他类似查询中使用它。

【讨论】:

busines-s-refid 不是整数,而是一个字符串,当我插入我的真实表时,查询返回 0 行。 我们可以修改这个查询来拆分月份的日期吗? @ShantanuDwivedi,提供表格ddl和样本数据 你能解释一下你在这个查询中做了什么吗? @ShantanuDwivedi,我试试,请问查询具体需要说明什么?【参考方案2】:

根据您的查询。检查下面的查询会有所帮助。

declare @BusinessGoal table  
(BusinessRefId varchar(50),   
Period varchar(50), 
GoalType varchar(100),    
Amount money, 
StartDateUtc datetime,   
EndDateUtc datetime, 
Currency varchar(10))


insert into @BusinessGoal values
('Business A',  'Year',    'CommittedTransactionFee', 45000,   '07/06/19', '00:00',      'USD'),
('Business B',  'Year',   'CommittedTransactionFee', 18000,   '07/06/17', '00:00',      'USD'),
('Business E',  'Year',    'CommittedTransactionFee', 5000 ,   '01/08/2019',  '01/04/2019',  'USD')

declare @tbl_year table 
(yyyy int,
period varchar(50))

insert @tbl_year values
(2015,'2015-2016'),
(2016,'2016-2017'),
(2017,'2017-2018'),
(2018,'2018-2019'),
(2019,'2019-2020'),
(2020,'2020-2021')



select 
a.BusinessRefId,
b.period,
a.GoalType,
a.Amount, 
DATEADD(YY,b.yyyy-YEAR(a.StartDateUtc),a.StartDateUtc) as StartDateUtc,
DATEADD(YY,b.yyyy-YEAR(a.StartDateUtc)+1,a.StartDateUtc) as EndDateUtc ,
a.Currency 
from @BusinessGoal a 
inner join @tbl_year b on b.yyyy  >=year(a.StartDateUtc)
where a.Period='Year' and b.yyyy <=YEAR(GETDATE()) order by a.BusinessRefId,b.period

样本输出

BusinessRefId|  period      |   GoalType                |   Amount  |   StartDateUtc|   EndDateUtc  |   Currency
---------------------------------------------------------------------------------------------------------------------------------------------------------------
Business A  |   2019-2020   |   CommittedTransactionFee |   45000   |   06/07/2019  |   06/07/2020  |   USD
Business B  |   2017-2018   |   CommittedTransactionFee |   18000   |   06/07/2017  |   06/07/2018  |   USD
Business B  |   2018-2019   |   CommittedTransactionFee |   18000   |   06/07/2018  |   06/07/2019  |   USD
Business B  |   2019-2020   |   CommittedTransactionFee |   18000   |   06/07/2019  |   06/07/2020  |   USD
Business E  |   2019-2020   |   CommittedTransactionFee |   5000    |   08/01/2019  |   08/01/2020  |   USD

【讨论】:

你能帮我把关于 BusinessGoal.Period = 'Month' 和 'Quarter' 的日期分开。我可以在这里或您喜欢的任何地方为您提供示例数据。 Ya ok.. 在这里提供样本数据及其每月和每季度的输出或有问题提及。【参考方案3】:
SELECT * FROM YourTableName
WHERE 
convert(DATETIME,tbl_Date)   BETWEEN Convert(DATETIME,CASE WHEN isnull(@FromDate,'')='' THEN jobMain_JobDate ELSE isnull(@FromDate,'') END)                     
AND Convert(DATETIME, CASE WHEN isnull(@ToDate,'')='' THEN tbl_Date ELSE isnull(@ToDate,'') END)

你可以试试这个Query...null部分也是Handle..

例如如果您仅输入 FromDate 作为“07/06/2017”,那么它将 给你从结果(“07/06/2017”到最后一个日期)

【讨论】:

【参考方案4】:

您可以获取开始和结束日期的年份,然后转换为字符串并连接如下

Declare @startdate as date,
 @enddate as date

 set @startdate='09-10-2017'
 set @enddate='07-12-2019'

select convert(varchar,year(@startdate))+'-'+convert(varchar,year(@enddate)) as Period

【讨论】:

这个拆分不是我在上面问题中提到的那个【参考方案5】:

根据样本数据和预期结果,您可以使用DATEADD() 函数和CROSS APPLY as 得到它

SELECT BusinessRefId,
       CONCAT(YEAR(DATEADD(Year, -1, SD)), '-', YEAR(SD)) Period,
       GoalType,
       Amount,
       DATEADD(Year, -1, SD) StartDateUtc,
       SD EndDateUtc,
       Currency
FROM
(
  VALUES
  ('Business B', 'Year', 'CommittedTransactionFee', 18000, '2017-06-07 00:00:00', NULL, 'USD')
)T(BusinessRefId, Period, GoalType, Amount, StartDateUtc, EndDateUtc, Currency)
CROSS APPLY
(
  VALUES
  (DATEADD(Year, 1, StartDateUtc)),
  (DATEADD(Year, 2, StartDateUtc)),
  (DATEADD(Year, 3, StartDateUtc))
) TT(SD)
ORDER BY SD DESC;

返回:

+---------------+-----------+-------------------------+--------+---------------------+---------------------+----------+
| BusinessRefId |  Period   |        GoalType         | Amount |    StartDateUtc     |     EndDateUtc      | Currency |
+---------------+-----------+-------------------------+--------+---------------------+---------------------+----------+
| Business B    | 2019-2020 | CommittedTransactionFee |  18000 | 07/06/2019 00:00:00 | 07/06/2020 00:00:00 | USD      |
| Business B    | 2018-2019 | CommittedTransactionFee |  18000 | 07/06/2018 00:00:00 | 07/06/2019 00:00:00 | USD      |
| Business B    | 2017-2018 | CommittedTransactionFee |  18000 | 07/06/2017 00:00:00 | 07/06/2018 00:00:00 | USD      |
+---------------+-----------+-------------------------+--------+---------------------+---------------------+----------+

Online Demo

【讨论】:

以上是关于sql server 中两个日期之间的年份以及每个日期在 sql server 中的开始和结束日期的主要内容,如果未能解决你的问题,请参考以下文章

SQL查询选择年份在两个日期之间的行

在 SQL Server 2008 中从月份和年份创建日期

检查日期是不是在 sql 中的日期范围之间(不检查年份)

SQL Server 2005获取任何年份中任何月份的第一个和最后一个日期

如何仅从 sql server 2008 中的日期中提取年份?

需要在 SQL Server 2008 中查找两个日期之间的日期