[英]SQL Server query for total number of days for a month between date ranges
I have specific date range like 我有特定的日期范围,例如
From Date To Date
---------------------------
2012-11-10 2012-11-15
2012-11-21 2012-11-22
2012-11-30 2012-12-01
I want to write a SQL query which calculates the total no of days between two dates and sum total number of days of particular month 我想编写一个SQL查询,该查询计算两个日期之间的天数总数和特定月份的天数总数
The output I wanted is, 我想要的输出是
No of days month
--------------------
9 11
1 12
Can anyone help me to write this SQL query? 谁能帮我写这个SQL查询吗?
Ideally, you have a table named "Dates" with all the dates you will ever use, eg year 1950 through 2100. This query will give you the result you want: 理想情况下,您有一个名为“日期”的表,其中包含您将要使用的所有日期,例如1950年至2100年。此查询将为您提供所需的结果:
select dateadd(m,datediff(m, 0, d.thedate),0) themonth, count(1)
from dates d
join ranges r on d.thedate between r.[from date] and r.[to date]
group by datediff(m, 0, d.thedate)
order by themonth;
Result: 结果:
| themonth | COLUMN_1 |
-------------------------
| 2012-11-01 | 9 |
| 2012-12-01 | 1 |
Note that instead of just showing "11" or "12" as month, which doesn't work well if you have ranges going above 12 months, or doesn't help sorting when it crosses a new year, this query shows the first day of the month instead. 请注意,此查询显示的是第一天,而不是仅将“ 11”或“ 12”显示为月份,如果您的范围超过12个月或者在新的一年中无济于事时,则不能很好地工作代替一个月。
If not, you can virtually create a dates
table on the fly, per the expanded query below: 如果没有,您可以按照下面的扩展查询在运行中虚拟地创建一个
dates
表:
;with dates(thedate) as (
select dateadd(yy,years.number,0)+days.number
from master..spt_values years
join master..spt_values days
on days.type='p' and days.number < datepart(dy,dateadd(yy,years.number+1,0)-1)
where years.type='p' and years.number between 100 and 150
-- note: 100-150 creates dates in the year range 2000-2050
-- adjust as required
)
select dateadd(m,datediff(m, 0, d.thedate),0) themonth, count(1)
from dates d
join ranges r on d.thedate between r.[from date] and r.[to date]
group by datediff(m, 0, d.thedate)
order by themonth;
The full working sample is given here: SQL Fiddle 此处提供了完整的工作示例: SQL Fiddle
尝试这个
select ((day(date_to)) - (day(date_from))) as no_of_days,month(date_from)as month from tablename
Pardon me for badly written SQL. 请原谅我编写的SQL不好。
The assumption is that the month diff. 假设是月份差异。 between fromdate and todate is 1.
在fromdate和todate之间是1。
Schema 架构
CREATE TABLE dateData
(fromdate datetime, todate datetime)
;
INSERT INTO dateData
(fromdate, todate)
VALUES
('2012-11-10', '2012-11-15'),
('2012-11-21', '2012-11-22'),
('2012-11-30', '2012-12-01')
;
SQL SQL
select mth, sum(days) as daysInMth
from
(
select month(fromdate) as mth,
sum(case
when month(fromdate) = month(todate) then datediff(dd, fromdate, todate)+1
else datediff(dd, fromdate, dateadd(mm, 1, fromdate) - day(fromdate)) + 1 end)
as days
from dateData
group by month(fromdate)
union
select month(todate) as mth,
sum(case when month(todate) <> month(fromdate) then
datediff(dd, fromdate, dateadd(mm, 1, fromdate) - day(fromdate)) + 1
else
case when month(todate) = month(fromdate) then 0 else
datediff(dd, convert(datetime, year(todate) + '-' + month(todate) + '-1'), todate)
end
end) as days
from dateData
group by month(todate)
) aggregated
group by mth
View on SQLFiddle: http://www.sqlfiddle.com/#!3/9f7da/56 在SQLFiddle上查看: http ://www.sqlfiddle.com/#!3 / 9f7da/56
I'd break it down into several steps (each given a separate CTE): 我将其分为几个步骤(每个步骤都有一个单独的CTE):
declare @Ranges table (FromDate date not null,ToDate date not null)
insert into @Ranges (FromDate,ToDate) values
('20121110','20121115'),
('20121121','20121122'),
('20121130','20121201')
;with Months as (
select
DATEADD(month,DATEDIFF(month,'20010101',FromDate),'20010101') as MonthStart,
DATEADD(month,DATEDIFF(month,'20010101',FromDate),'20010131') as MonthEnd
from @Ranges
union /* not all */
select
DATEADD(month,DATEDIFF(month,'20010101',ToDate),'20010101') as MonthStart,
DATEADD(month,DATEDIFF(month,'20010101',ToDate),'20010131') as MonthEnd
from @Ranges
), MonthRanges as (
select
CASE WHEN r.FromDate > m.MonthStart then r.FromDate ELSE m.MonthStart END as StartRange,
CASE WHEN r.ToDate < m.MonthEnd then r.ToDate ELSE m.MonthEnd END as EndRange
from
@Ranges r
inner join
Months m
on
r.ToDate >= m.MonthStart and
r.FromDate <= m.MonthEnd
)
select
DATEPART(month,StartRange),
SUM(DATEDIFF(day,StartRange,EndRange)+1) /* Inclusive */
from
MonthRanges
group by
DATEPART(month,StartRange)
First, the Months
CTE finds the first and last days of each month that we might be interested in(*). 首先,
Months
CTE查找我们可能感兴趣的每个月的第一天和最后一天(*)。 Then, MonthRanges
recombines this data with the original ranges and splits them as required so that each period we're dealing with only represents days from a single month. 然后,
MonthRanges
将此数据与原始范围重新组合,并根据需要对其进行拆分,以便我们处理的每个期间仅代表一个月中的几天。 Then we can just use DATEDIFF
to calculate the number of days that each range spans (and add 1 since we're dealing with dates and want inclusive values) 然后,我们可以使用
DATEDIFF
来计算每个范围的天数(并添加1,因为我们正在处理日期并且需要包含值)
(*) the Months
CTE will work provided that we're not dealing with any ranges that span over multiple months and where no other ranges start or end in the intervening months. (*)如果我们不处理跨多个月的任何范围,并且在随后的几个月中没有其他范围开始或结束,则CTE
Months
将起作用。 If you need to cope with this situation, I need to revise the Months
CTE. 如果您需要应对这种情况,我需要修改
Months
CTE。 Eg if we add ('20120115','20120315')
(and no other range) to the above sample, we won't get a result for February using the above. 例如,如果将
('20120115','20120315')
(而不添加其他范围)添加到上述示例中,则使用上述示例将不会获得2月份的结果。 Do we need to cope with this situation? 我们需要应付这种情况吗?
To cope with the situation noted in (*), we can replace the Months
CTE in the above query with: 为了解决(*)中提到的情况,我们可以将上述查询中的
Months
CTE替换为:
;With LastMonth as (
select MAX(ToDate) as Mx from @Ranges
), MultiMonths as (
select
DATEADD(month,DATEDIFF(month,'20010101',FromDate),'20010101') as MonthStart,
DATEADD(month,DATEDIFF(month,'20010101',FromDate),'20010131') as MonthEnd
from @Ranges
union all
select
DATEADD(month,1,MonthStart),
DATEADD(month,1,MonthEnd)
from MultiMonths
where MonthStart <= (select Mx from LastMonth)
), Months as (
select distinct MonthStart,MonthEnd from MultiMonths
)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.