按日期分组并检查连续日期

时间:2013-03-28 12:47:48

标签: sql tsql group-by common-table-expression

我有一组像这样的数据

date1       Price  Availability  ServiceID
2012-10-01  50     1             5
2012-10-02  60     1             5
2012-10-03  60     1             5
2012-10-04  60     1             5
2012-10-06  60     1             5
2012-10-07  60     0             5
2012-10-08  60     1             5

现在我想查看特定时期的总价,最低可用性和服务费是多少

例如

from 2012-10-01 to 2012-10-03 results would be 170, availability 1 and serviceID 5
from 2012-10-06 to 2012-10-08 results would be 180, availability 0! and serviceID 5
from 2012-10-04 to 2012-10-06 results would be 120, availability 1! and serviceID 5 BUT there is a date missing so availability is 0!

我试过像

这样的东西
select date1, sum(price), min(availability), service from #t
group by date1, price, availability, service
having count(date1) = datediff(day, @startdate, @enddate)

这不起作用,因为如果我按date1分组,则计数无效。不知道如何获得总和,最小可用性并检查连续日期。

修改 如果我想要一个结果集包含详细的规范。并使用min(可用性)= 0或非连续日期过滤掉结果

For example
from 2012-10-01 to 2012-10-03 results would be 170, availability 1 and serviceID 5

date1       Price  Availability  ServiceID
    2012-10-01  50     1             5
    2012-10-02  60     1             5
    2012-10-03  60     1             5

from 2012-10-06 to 2012-10-08 results would be 180, availability 0! and serviceID 5
date1       Price  Availability  ServiceID

from 2012-10-04 to 2012-10-06 results would be 120, availability 1! and serviceID 5 BUT 
date1       Price  Availability  ServiceID

2 个答案:

答案 0 :(得分:2)

试试这个:

select  sum(price) As TotalPrice, 
        service,
        Case When Count(*) = DateDiff(Day, @Startdate, @EndDate) + 1 
                Then Min(Availability)
                Else 0 End As Availability
from    #T
Where   Date1 >= @StartDate
        And Date1 <= @endDate
group by service

通过基于日期过滤where子句中的日期,而不是按日期分组,这允许您获得一个或多个行,然后您可以将它们与日期差异相匹配。请注意,您需要在日期差异中添加1,因为从昨天到今天的DateDiff只有1,但在源数据中代表2行。

我还应该提到,这实际上并不是在检查连续日期。它只是查找相应的行数以匹配计算的天数。

根据您的评论和编辑,您可能想要尝试此衍生的表格解决方案。

Select  T.date1,
        SummaryData.TotalPrice,
        SummaryData.Availability,
        T.Service
From    #T T
        Inner Join (
            select  sum(price) As TotalPrice, 
            service,
                Case When Count(*) = DateDiff(Day, @Startdate, @EndDate) + 1 
                     Then Min(Availability)
                     Else 0 End As Availability
            from    #T
            Where   Date1 >= @StartDate
                    And Date1 <= @endDate
            group by service
            Having Case When Count(*) = DateDiff(Day, @Startdate, @EndDate) + 1 
                        Then Min(Availability)
                        Else 0 End = 1 
            ) As SummaryData
            On T.Service = SummaryData.Service
Where   Date1 >= @StartDate
        And Date1 <= @endDate

答案 1 :(得分:0)

如果没有缺少日期的曲线球,查询将非常简单:

SELECT SUM(price), MIN(availability) AS Availibility, MIN(serviceID) AS serviceID FROM #t
WHERE date1 BETWEEN @Startdate AND @enddate

然而,找到缺少的日期需要一个额外的CTE,我会使用来自t-sql get all dates between 2 dates的想法,它可能看起来像这样:

;WITH dates AS (
  SELECT @startdate AS dt
  UNION ALL
  SELECT DATEADD(dd, 1, dt)
    FROM dates s
   WHERE DATEADD(dd, 1, dt) <= @enddate
)
SELECT SUM(price), 
CASE 
    WHEN EXISTS (SELECT * FROM dates WHERE dt NOT IN (SELECT date1 FROM #t WHERE date1 BETWEEN @Startdate AND @enddate)) THEN 0
    ELSE MIN(availability) 
END AS Availibility, 
MIN(serviceID) AS serviceID FROM #t
WHERE date1 BETWEEN @Startdate AND @enddate