T-SQL从表

时间:2017-10-09 18:12:55

标签: sql sql-server

让我们说我有一个查询,其中我计算每天的事件数量:

**Date**        **NumberOfEvents**
2017-11-1       7
2017-11-2       11
2017-11-3       3
...
2017-11-8       24
2017-11-9       6
2017-11-10      10
2017-11-11      9
...
2017-11-22      22
2017-11-23      11
2017-11-24      14
2017-11-25      17
...      
2017-11-28      16
2017-11-29      21
2017-11-30      6
...

然后让我说我会定义变量@StartingDay ='2017-11-3'

我希望在@StartingDay之后的下一个4周内获得同一工作日+ -1天的最小值的查询,p.ex:

**Period**                   **DateWithMin**   **MinNumberOfEvents**
2017-11-09 To 2017-11-11     2017-11-9         6
2017-11-16 To 2017-11-18     2017-11-17        8
2017-11-23 To 2017-11-25     2017-11-23        11
2017-11-30 To 2017-12-02     2017-11-30        6

我相信我必须在不同时期循环才能寻找分钟,但我无法找到循环的方法。

2 个答案:

答案 0 :(得分:2)

您可以使用模数和日期算法来获取时间段和组:

select min(date), max(date), min(NumberOfEvents)
from t
where (datediff(day, @startingday, date) % 7) in (0, 1, 6) and
      date > dateadd(day, 1, @startingday) and
      date <= dateadd(day, 4 * 7 + 1, @startingday)
group by (datediff(day, @startingday, date) + 1) / 7;

获取最小事件的日期更加麻烦。这是一种方法:

select min(date), max(date), min(NumberOfEvents),
       max(case when seqnum = 1 then date end) as date_at_min
from (select t.*, v.grp,
             row_number() over (partition by grp order by numberofevents) as seqnum
      from t cross apply
           (values ((datediff(day, @startingday, date) + 1) / 7)) v(grp)
     ) t
where (datediff(day, @startingday, date) % 7) in (0, 1, 6) and
      date > dateadd(day, 1, @startingday) and
      date <= dateadd(day, 4 * 7 + 1, @startingday)
group by grp;

答案 1 :(得分:2)

另一种方法是使用递归CTE生成FromTo日期,对结果应用Row_Number()以查找每个分组Min,并只选择那些结果:

Declare @StartingDay    Date = '2017-11-03',
        @NumWeeks       Int = 4

;With Dates As
(
    Select  DateFrom    = DateAdd(Day, -1, DateAdd(Week, 1, @StartingDay)),
            DateTo      = DateAdd(Day, 1, DateAdd(Week, 1, @StartingDay))
    Union All
    Select  DateFrom    = DateAdd(Week, 1, DateFrom),
            DateTo      = DateAdd(Week, 1, DateTo)  
    From    Dates
    Where   DateTo < DateAdd(Day, 1, DateAdd(Week, @NumWeeks, @StartingDay))
), Results As
(
    Select  PeriodFrom      = D.DateFrom,
            PeriodTo        = D.DateTo,
            NumberOfEvents  = Y.NumberOfEvents,
            RN              = Row_Number() Over (Partition By D.DateFrom, D.DateTo 
                                                 Order By Y.NumberOfEvents),
            Date            = Y.Date
    From    YourTable   Y
    Join    Dates       D   On  Y.Date Between D.DateFrom And D.DateTo
)
Select  PeriodFrom, 
        PeriodTo, 
        DateWithMin         = Date, 
        MinNumberOfEvents   = NumberOfEvents
From    Results
Where   RN = 1