如何获得范围内一年中特定月份的天数总和
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:
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_date
到 end_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
如果我的假期 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:
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_date
到 end_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