如何获得范围内一年中特定月份的天数总和

How to get the summation of days in specific month of year in range

如果我的假期 table 具有以下结构:

emp_num start_date   end_date
 234     8-2-2015    8-5-2015
 234     6-28-2015   7-1-2015
 234     8-29-2015   9-2-2015
 115     6-7-2015    6-7-2015
 115     8-7-2015    8-10-2015

考虑到日期格式是:m/dd/yyyy

我怎样才能得到每个员工在特定月份的假期总和。

说我想在 8Aug-2015

休假

我想要这样的结果

emp_num   sum
234        7
115        4

7 = 8-2-2015 and 8-5-2015 plus 之间的所有天 8-29-2015 AND 8-31-2015 月底之间的所有天

试试这个

  with cte(
  Select emp_num,DATEDIFF(day,start_date,end_date) AS sum_day from table_Name
  Group by emp_num,start_date,end_date
  )
  Select emp_num,sum(sum_day) as sum_day from cte group by emp_num
Select(emp_name,start_date,end_date) AS sum_day from table_Name Group by emp_num,start_date,end_date

使用 Tally Table:

SQL Fiddle

DECLARE @month INT,
        @year  INT

SELECT @month = 8, @year = 2015

--SELECT
--  DATEADD(MONTH, @month - 1, DATEADD(YEAR, @year - 1900, 0)) AS start_day, 
--  DATEADD(MONTH, @month, DATEADD(YEAR, @year - 1900, 0)) AS end_d

;WITH CteVacation AS(
    SELECT 
        emp_num, 
        start_date = CONVERT(DATE, start_date, 101),
        end_date = CONVERT(DATE, end_date, 101) 
    FROM vacation
)
,E1(N) AS(
    SELECT * FROM(VALUES
        (1),(1),(1),(1),(1),(1),(1),(1),(1),(1)
    )t(N)
),
E2(N) AS(SELECT 1 FROM E1 a CROSS JOIN E1 b),
E4(N) AS(SELECT 1 FROM E2 a CROSS JOIN E2 b),
Tally(N) AS(
    SELECT TOP(SELECT MAX(DATEDIFF(DAY, start_date, end_date)) FROM vacation)
        ROW_NUMBER() OVER(ORDER BY (SELECT NULL))
    FROM E4
)
SELECT
    v.emp_num,
    COUNT(*)
FROM CteVacation v
CROSS JOIN Tally t
WHERE
    DATEADD(DAY, t.N - 1, v.start_date) <= v.end_date
    AND DATEADD(DAY, t.N - 1, v.start_date) >= DATEADD(MONTH, @month - 1, DATEADD(YEAR, @year - 1900, 0))
    AND DATEADD(DAY, t.N - 1, v.start_date) < DATEADD(MONTH, @month, DATEADD(YEAR, @year - 1900, 0))
GROUP BY v.emp_num

首先,您想使用正确的数据类型来简化您的计算。在我的解决方案中,我使用 CTE 来格式化您的数据类型。然后建立一个计数 table 从 1 到所有假期的最大持续时间。使用该计数 table,在 vacation table 上执行 CROSS JOIN 以生成从其 start_dateend_date 的所有假期日期。

之后,添加一个 WHERE 子句来过滤落在传递的 month-year 参数上的日期。

这里,@month@year被声明为INT。您想要的是获取从 month-year 的第一天到最后一天的所有日期。 month 第一天的公式是:

DATEADD(MONTH, @month - 1, DATEADD(YEAR, @year - 1900, 0)) 

而对于 month 的最后一天,在上面加上一个月,只需使用 <:

DATEADD(MONTH, @month, DATEADD(YEAR, @year - 1900, 0))

希望对您有所帮助

declare @temp table
(emp_num int, startdate date, enddate date)


 insert into @temp values (234,'8-2-2015','8-5-2015')
 insert into @temp values (234,'6-28-2015','7-1-2015')
 insert into @temp values (234,'8-29-2015','9-2-2015')
 insert into @temp values (115,'6-7-2015','6-7-2015')
 insert into @temp values (115,'8-7-2015','8-10-2015')
-- i am passing 8 as month number in your case is August
 select emp_num,
 SUM(
 DATEDIFF (DAY , startdate,  
 case when MONTH(enddate) = 8
            then enddate
            else DATEADD(s,-1,DATEADD(mm, DATEDIFF(m,0,startdate)+1,0))--end date of month
            end
 )+1) AS Vacation from @temp
 where (month(startdate) = 8 OR month(enddate) = 8) AND (Year(enddate)=2015 AND Year(enddate)=2015)
 group by emp_num

UPDATE 在有效评论后:这将因以下日期而失败:2015-07-01、2015-09-30 –@ t-clausen.dk
我被认为 OP 只想要一个月,他会通过

declare @temp table
(emp_num int, startdate date, enddate date)


 insert into @temp values (234,'8-2-2015','8-5-2015')
 insert into @temp values (234,'6-28-2015','7-1-2015')
 insert into @temp values (234,'8-29-2015','9-2-2015')
 insert into @temp values (115,'6-7-2015','6-7-2015')
 insert into @temp values (115,'8-7-2015','8-10-2015')

 insert into @temp values (116,'07-01-2015','9-30-2015')


 select emp_num,
 SUM(
 DATEDIFF (DAY , startdate,  
 case when MONTH(enddate) = 8 
            then enddate
            else DATEADD(s,-1,DATEADD(mm, DATEDIFF(m,0,startdate)+1,0))
            end
 )+1) AS Vacation from @temp
 where (Year(enddate)=2015 AND Year(enddate)=2015) 
 AND 8 between MONTH(startdate) AND MONTH(enddate)
 group by emp_num

这将适用于 sqlserver 2012+

DECLARE @t table
(emp_num int, start_date date, end_date date)
INSERT @t values
( 234, '8-2-2015' , '8-5-2015'),
( 234, '6-28-2015', '7-1-2015'),
( 234, '8-29-2015', '9-2-2015'),
( 115, '6-7-2015' , '6-7-2015'),
( 115, '8-7-2015' , '8-10-2015')


DECLARE @date date = '2015-08-01'

SELECT
   emp_num,
   SUM(DATEDIFF(day, 
                CASE WHEN @date > start_date THEN @date ELSE start_date END,
                CASE WHEN EOMONTH(@date) < end_date 
                     THEN EOMONTH(@date)
                     ELSE end_date END)+1) [sum]
FROM @t
WHERE 
  start_date <= EOMONTH(@date)
  and end_date >= @date
GROUP BY emp_num