繁体   English   中英

日期范围内的SQL Server计数天数

[英]Sql server Count Days within Date Range

这是表(SQL Server)中的示例:

Start       End
2014-08-31  2014-09-01 
2014-09-09  2014-09-11 
2014-09-11  2014-09-26 
2014-09-15  2014-09-23 
2014-09-16  2014-09-22 
2014-09-17  2014-09-19 
2014-09-17  2014-09-26 
2014-09-17  2014-10-03 
2014-09-17  2014-09-26 
2014-09-17  2014-09-18 
2014-09-18  2014-10-04 
2014-09-18  2014-09-19 
2014-09-18  2014-09-19 
2014-09-19  2014-09-20 

这是请假申请表。 我需要获取每天的总数。 输出应该是这样的。

2014-08-31 == 1
2014-09-01 == 1
2014-09-09 == 1
2014-09-10 == 1
2014-09-11 == 2
2014-09-12 == 1
2014-09-13 == 1
2014-09-14 == 1
2014-09-15 == 2
2014-09-16 == 2
2014-09-17 == 8
2014-09-18 == 11
2014-09-19 == 11
2014-09-20 == 8

使用LEFT JOIN

SQL小提琴

SELECT
    l.dt, COUNT(t.Start) AS cnt
FROM Leave l
LEFT JOIN tbl t
    ON dt BETWEEN Start AND [End]
GROUP BY l.dt

使用OUTER APPLY

SQL小提琴

SELECT
    l.dt, a.cnt
FROM Leave l
OUTER APPLY(
    SELECT COUNT(*) AS cnt
    FROM tbl
    WHERE dt BETWEEN Start AND [End]
)a

如果您确实没有请假表,则可以创建一个动态的请假表。 使用与Felix提到的类似的理论,这是构造查询的方式:

SQLFiddle: http ://sqlfiddle.com/#!6/750b9/16

create table test (starting date, ending date);
insert into test values
('2014-08-31','2014-09-01'),
...

现在查询:

with
-- create a dynamic in-memory table holding a list of dates
datecte as
(
  select cast('2014-08-01' as datetime) dateval
  union all
  select dateval+1 from datecte where dateval+1 < '2014-09-30'
), 
-- call it leave
leave as 
(
  select dateval from datecte
)
-- combine the dynamically created in-memory date table
-- with actual dataset
select l.dateval, count(t.starting) as counter
from leave l
left join test t
  on dateval between starting and ending
group by l.dateval
having count(t.starting) > 0

结果:

|                     dateval | counter |
|-----------------------------|---------|
|    August, 31 2014 00:00:00 |       1 |
| September, 01 2014 00:00:00 |       1 |
| September, 09 2014 00:00:00 |       1 |
| September, 10 2014 00:00:00 |       1 |
| September, 11 2014 00:00:00 |       2 |
| September, 12 2014 00:00:00 |       1 |
| September, 13 2014 00:00:00 |       1 |
| September, 14 2014 00:00:00 |       1 |
| September, 15 2014 00:00:00 |       2 |
| September, 16 2014 00:00:00 |       3 |
| September, 17 2014 00:00:00 |       8 |
| September, 18 2014 00:00:00 |      11 |
| September, 19 2014 00:00:00 |      11 |
| September, 20 2014 00:00:00 |       8 |
| September, 21 2014 00:00:00 |       7 |
| September, 22 2014 00:00:00 |       7 |
| September, 23 2014 00:00:00 |       6 |
| September, 24 2014 00:00:00 |       5 |
| September, 25 2014 00:00:00 |       5 |
| September, 26 2014 00:00:00 |       5 |
| September, 27 2014 00:00:00 |       2 |
| September, 28 2014 00:00:00 |       2 |
| September, 29 2014 00:00:00 |       2 |

SQLFiddle完整版: http ://sqlfiddle.com/#!6 / 750b9 / 17

我只想分享我的决心。

tb_LeaveRequest
id  StartDate   EndDate
1   09/17/2014  09/18/2014
2   09/18/2014  10/04/2014
3   09/17/2014  10/03/2014
4   09/17/2014  09/26/2014
5   09/18/2014  09/19/2014
6   09/25/2014  09/25/2014
7   09/26/2014  09/26/2014
8   09/19/2014  09/20/2014
9   09/25/2014  09/25/2014
10  09/17/2014  09/19/2014
11  09/09/2014  09/11/2014
12  09/18/2014  09/19/2014
13  09/11/2014  09/26/2014
14  09/22/2014  09/23/2014
15  09/22/2014  09/23/2014
16  09/22/2014  09/22/2014
17  09/23/2014  09/23/2014
18  09/24/2014  09/24/2014
19  09/15/2014  09/23/2014
20  09/25/2014  09/25/2014
22  09/26/2014  09/26/2014
23  09/23/2014  09/23/2014
24  09/17/2014  09/26/2014
26  09/22/2014  09/22/2014
27  09/16/2014  09/22/2014
28  09/22/2014  09/22/2014

上面是tb_LeaveRequest表中的数据

这是我的查询如下:

--Create temp table for tb_LeaveRequest with IsProcssed Column
    CREATE TABLE #tmpLeaveRequest (id int, StartDate datetime, EndDate datetime, IsProcessed bit)

    --Insert tb_LeaveRequest in temp table
    insert INTO #tmpLeaveRequest(id, StartDate, EndDate, IsProcessed)
    Select  id, StartDate, EndDate, 0 from tb_LeaveRequest
    Order by StartDate

    --Create temp table for out
    CREATE TABLE #tmpOutput (Dys datetime, Counts   int)

    While (Select Count(*) From #tmpLeaveRequest Where IsProcessed = 0) > 0
    Begin
        DECLARE @Id as int
        DECLARE @StartDate as datetime
        DECLARE @DateDiff INT = 0;

        DECLARE @cnt INT = 0;
        Declare @NewDate as datetime

        Select Top 1 @Id = Id, @StartDate = StartDate, @DateDiff = DATEDIFF(D, StartDate, EndDate) From #tmpLeaveRequest Where IsProcessed = 0
        ----    
        WHILE (@cnt <= @DateDiff)
        BEGIN

            set @NewDate = DATEADD(day, @cnt, @StartDate) 

            if exists(select * from #tmpOutput where Dys = @NewDate)
            Begin
                Update #tmpOutput
                Set Counts = Counts + 1
                Where Dys = @NewDate
            End
            else 
            BEGIN
                Insert into #tmpOutput (Dys, Counts) values (@NewDate, 1)
            end

            set @cnt = @cnt + 1

        END --End Loop

        Update #tmpLeaveRequest Set IsProcessed = 1 Where Id = @Id 

    End --End Loop

    --Output
    Select * From #tmpOutput
    Order BY Dys


    --Drop tmp Table
    DROP TABLE #tmpOutput
    DROP TABLE #tmpLeaveRequest

可能是:

Dys Counts
09/09/2014  1
09/10/2014  1
09/11/2014  2
09/12/2014  1
09/13/2014  1
09/14/2014  1
09/15/2014  2
09/16/2014  3
09/17/2014  8
09/18/2014  11
09/19/2014  11
09/20/2014  8
09/21/2014  7
09/22/2014  12
09/23/2014  10
09/24/2014  6
09/25/2014  8
09/26/2014  7
09/27/2014  2
09/28/2014  2
09/29/2014  2
09/30/2014  2
10/01/2014  2
10/02/2014  2
10/03/2014  2
10/04/2014  1

这是语法

    SELECT DATEDIFF(dd, Start, End) FROM TableName

    SELECT DATEDIFF(dd,'2014-08-31', '2014-09-01') AS 'DaysCount' 
    FROM TableName -- result: 1

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM