【问题标题】:Group by date and and check for continuous dates按日期分组并检查连续日期
【发布时间】:2013-03-28 12:47:48
【问题描述】:

我有一组这样的数据

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

现在我想检查特定时期的总价、最低可用性和 serviceid 是多少

例如

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(availability) = 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

【问题讨论】:

  • 如果 2012-10-04 到 2012-10-06 有 2 个值,每个值为 60,那么结果怎么可能是 180?你需要一个“假”60 来代替缺失的日期吗?

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


【解决方案1】:

试试这个:

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

【讨论】:

  • 基本上我需要一个 cte 或一个临时表。一次查询无法解决?
  • 可以在不使用 CTE 的情况下创建与上面显示的相同的输出,但在不使用 CTE 的情况下可能无法包含详细信息,除非您使用的是较新版本的 SQL Server。你用的是什么版本?
【解决方案2】:

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

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

【讨论】:

  • 当我输入 G Mastros 时,我也发布了一个我比我更喜欢的解决方案 :) 但决定也发布这个。从两侧看也无妨。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-12-06
  • 1970-01-01
  • 1970-01-01
  • 2023-01-17
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多