2017-12-18 312 views
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) 

哪里,这是给我的EXP ected输出:

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

由于分组由“开始日期”,我怎么能算在本月行的每一个它扩展跨越?

+0

是否有一个起始日期为每月,以便选择不同的StatDate将提供所需月份的完整列表? – Turo

+0

每条记录​​都有一个开始日期和结束日期,但这些记录可能会重叠,因为一条记录可能会延长1个月以上。希望它是有道理的 –

回答

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

你的解决方案可能会工作,但我不想创建第二个表,只是几个月,像feb可以变化,对不对?必须有一种方法来创建一个存储的专业或视图来完成这项工作。 –

+0

您可以使用类似于[** this **]的查询来创建cte(https://stackoverflow.com/questions/1378593/get-a-list-of-dates-between-two-dates-using-a功能),以便您即时创建日期。但是创建一个有几个月的表并不贵,100年只需要1200行 –

+0

您可以使用前面的查询来获取'startDate'和[** EOMONTH **](https://docs.microsoft.com/en-us/sql/t-sql/functions/emonth-transact-sql)得到'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 
+0

您需要将'COUNT(*)'更改为'COUNT(y.start)'类似的东西'否则您将在未得到结果时得到1。 –

+0

是的,我注意到这一点,并作出了改变,谢谢:-) –

相关问题