MSSQL日期范围报告 - 每月的天数

时间:2015-05-20 22:34:19

标签: sql-server

我有一个包含“开始日期”和“结束日期”列的实例表。这是一个简单的例子:

ID     StartDate     EndDate
 1     1/8/2015      1/10/2015
 2     1/8/2015      1/15/2015
 3     2/6/2015      3/2/2015
 4     1/6/2015      2/20/2015
 5     3/18/2015     4/2/2015

我正在尝试编写一个查询来查明给定月份发生了多少天,但是有些实例重叠并跨越了多个月,这使得它变得困难。我想要的结果看起来像这样:

Month        # of days
January      26 (earliest is ID 4 starting 1/6)
February     28 (entire month because of ID 3 and 4)
March        16 (2 days from ID 3, 14 days from ID 5)
April        2 (first 2 days of the month from ID 5)
May          0

非常感谢任何帮助。谢谢!

3 个答案:

答案 0 :(得分:0)

问题太复杂了;

在我看来,你需要编写一个计算"唯一"的数量的函数。记录中提到的天数。

我没有写这个函数,但是这个新函数" num"的设计是这样的:

1- It should get the month and year (named aMonth and aYear). 
2- It Finds all records that have at least a day in aYear/aMonth:
    (month(startDate)=aMonth and year(startDate)=aYear)
    or
    (month(endDate)=aMonth and year(endDate)=aYear)
    or
    (
        ((month(startDate)<aMonth and year(startDate)=aYear) or (year(startDate)<aYear))
        and 
        ((month(endDate)>aMonth and year(endDate)=aYear) or (year(endDate)>aYear))
    )

3- Over these records, it should open a cursor, and process the records one by one.

4- While processing each records of the cursor, you can count the days of the month and store them in an array (or 28-31 character string of 0/1, for example).

5- count the number of 1's of this array (or string) and return it.

写完这个函数(&#34; num&#34;)后,答案的高级将是这样的:

Select 'January', dbo.num(1, 2015) as days
union all
Select 'February', dbo.num(2, 2015) as days
union all
Select 'March', dbo.num(3, 2015) as days
union all
Select 'April', dbo.num(4, 2015) as days
union all
Select 'May', dbo.num(5, 2015) as days
union all
Select 'June', dbo.num(6, 2015) as days
union all
Select 'July', dbo.num(7, 2015) as days
union all
Select 'August', dbo.num(8, 2015) as days
union all
Select 'September', dbo.num(9, 2015) as days
union all
Select 'October', dbo.num(10, 2015) as days
union all
Select 'November', dbo.num(11, 2015) as days
union all
Select 'December', dbo.num(12, 2015) as days

答案 1 :(得分:0)

如果只计算同一年的天数,可以试试这个。我只构建了两个月的代码,但很容易扩展它。

SELECT 
 (SELECT SUM(CASE WHEN sdate>='2015-2-1' OR edate<'2015-1-1' THEN 0 
     WHEN edate>='2015-2-1' THEN datediff(day, sdate, '2015-2-1')
     ELSE datediff(day,sdate,edate) END) 
     FROM a1)
     AS Jan_Days,
 (SELECT SUM(CASE WHEN sdate>='2015-3-1' OR edate<'2015-2-1' THEN 0 
     WHEN edate>='2015-3-1' THEN datediff(day, sdate, '2015-3-1')
     ELSE datediff(day,sdate,edate) END) 
     from a1 ) 
    AS Feb_Days,
 ...

远非效率。使用在记录中运行的脚本或存储过程并计算结果会更有效。

答案 2 :(得分:0)

Ĵ,

请检查下面的SQL脚本。 在运行脚本之前,您将意识到我已经使用SQL Dates table实际上是一个返回临时日期表的SQL函数。 您可以在给定的教程中找到源代码

我还使用了multiple CTE queries

;with dates as (
select 
    cast(date as date) date
from [dbo].[DateTable]('1/1/2015','12/31/2015')
), cte as (
    select 
        distinct date
    from instances, dates
    where dates.date between instances.startdate and instances.enddate
)
select
    year(date) year, month(date) month, count(*) dayscount
from cte
group by year(date), month(date)

顺便说一句,三月返回16天,其中一天是2天,另一天是14天。

我希望Select语句很有用,