计算每个时间行出现在2个日期之间的范围内

问题描述 投票:2回答:2

我试图计算一行在两个日期之间“出现”a的次数,并按月分组。

所以,假设我的行看起来像这样:

   Name    |  StartDate      | EndDate 
-----------|-----------------|------------
   Mathias | 2017-01-01      | 2017-04-01
   Lucas   | 2017-01-01      | 2017-04-01

我想得到输出,显示查询中的两个日期之间存在多少记录,所以类似于以下输出:

   Count   |    Year         | Month 
-----------|-----------------|------------
   2       | 2017            | 1
   2       | 2017            | 2
   2       | 2017            | 3
   2       | 2017            | 4
   0       | 2017            | 5
   0       | 2017            | 6

我试过的是:

SELECT COUNT(*) as COUNT, YEAR(StartDate) YEAR, MONTH(StartDate) MONTH
FROM NamesTable
 WHERE Start >= '2017-01-01 00:00:00'
 AND Slut <= '2017-06-01 00:00:00'
 group by YEAR(StartDate), MONTH(StartDate)

这给了我预期的输出:

   Count   |    Year         | Month 
-----------|-----------------|------------
   2       | 2017            | 1
   0       | 2017            | 2
   0       | 2017            | 3
   0       | 2017            | 4
   0       | 2017            | 5
   0       | 2017            | 6

由于按“开始日期”进行分组,如何计算每月扩展的行数?

sql tsql
2个回答
0
投票

你需要一个月份范围的表

allMonths

+---------+------------+------------+
| monthId | StartDate  |  EndDate   |
+---------+------------+------------+
|       1 | 2017-01-01 | 2017-01-02 |
|       2 | 2017-01-02 | 2017-01-03 |
|       3 | 2017-01-03 | 2017-01-04 |
|       4 | 2017-01-04 | 2017-01-05 |
|       5 | 2017-01-05 | 2017-01-06 |
|       6 | 2017-01-06 | 2017-01-07 |
|       7 | 2017-01-07 | 2017-01-08 |
|       8 | 2017-01-08 | 2017-01-09 |
|       9 | 2017-01-09 | 2017-01-10 |
|      10 | 2017-01-10 | 2017-01-11 |
|      11 | 2017-01-11 | 2017-01-12 |
|      12 | 2017-01-12 | 2018-01-01 |
+---------+------------+------------+

然后你的查询是:

SELECT am.startDate, COUNT(y.Name)
FROM allMonths am
LEFT JOIN yourTable y
  ON am.StartDate <= y.EndDate
 AND am.EndDate >= y.StartDate
GROUP BY am.startDate

注意:您需要检查边框情况。也许您需要将>=更改为>或将EndDate更改为该月的最后一天。


0
投票

所以,我最终做的就像胡安·卡洛斯提出的那样,但是我没有创建一张桌子,而是用CTE代替了一个更清洁的方法:

Declare @todate datetime, @fromdate datetime, @firstOfMonth datetime, @lastOfMonth datetime
Select 
@fromdate='2017-01-11', 
@todate='2017-12-21',
@firstOfMonth =  DATEADD(month, DATEDIFF(month, 0, @fromdate), 0), ----YEAR(@fromdate) + MONTH(@fromdate) + DAY(1),
@lastOfMonth = DATEADD(month, ((YEAR(@fromdate) - 1900) * 12) + MONTH(@fromdate), -1)

 ;with MonthTable (MonthId, StartOfMonth, EndOfMonth) as
 (
        SELECT MONTH(@firstOfMonth) as MonthId, @firstOfMonth as StartOfMonth, @lastOfMonth as EndOfMonth
        UNION ALL   
        SELECT MONTH(DATEADD(MONTH, 1, StartOfMonth)), DATEADD(MONTH, 1, StartOfMonth), DATEADD(MONTH, 1, EndOfMonth)
        FROM MonthTable
         WHERE StartOfMonth <= @todate
 )

 SELECT am.StartOfMonth, COUNT(y.Start) as count
FROM MonthTable am
left JOIN clientList y
    ON y.Start <= am.StartOfMonth
    AND y.End >= am.EndOfMonth
GROUP BY am.StartOfMonth
© www.soinside.com 2019 - 2024. All rights reserved.