按时间间隔对销售数据进行分组,每15分钟一天

时间:2017-05-30 20:52:09

标签: sql sql-server tsql sql-server-2012

我有一个销售表,它包含不同商店的销售数据和时间,让我们说在一天和一个商店我们做了10,000交易然后我需要找到每15分钟的总销售额对于该特定的营业日期,请记住:例如:如果在中午12:00到下午12:15之间没有销售,那么它应该为零或为零。

在一天中我们有24小时,所以它意味着在15分钟间隔内有96列。

Sales Table:

SiteName          Time          Amount        BusinessDate
----------------------------------------------------------
A                7:01:02 AM     20            2017-01-02
A                7:03:22 AM     25            2017-01-02
A                7:05:03 AM     33            2017-01-02
A                7:11:02 AM     55            2017-01-02
A                7:13:05 AM     46            2017-01-02
A                7:17:02 AM     21            2017-01-02
A                8:01:52 AM     18            2017-01-02
A                8:55:42 AM     7             2017-01-02
A                8:56:33 AM     7             2017-01-02
A                8:58:55 AM     31            2017-01-02

等等

我怎样才能做到这一点?!

4 个答案:

答案 0 :(得分:2)

动态示例

Declare @SQL varchar(max) = Stuff((Select ',' + QuoteName(T) 
                                    From (Select Top 96 T=format(DateAdd(Minute,(Row_Number() Over (Order By (Select null))-1)*15,0),'HH:mm') From  master..spt_values n1) A
                                    Order by 1 
                                    For XML Path('')),1,1,'') 
Select  @SQL = '
Select *
From (
        Select [SiteName]
              ,Col   = format(DateAdd(MINUTE,(DatePart(HOUR,[Time])*60) + ((DatePart(MINUTE,[Time]) / 15)*15),0),''HH:mm'')
              ,Value = [Amount]
         From  Sales 
     ) A
Pivot (sum(Value) For [Col] in (' + @SQL + ') ) p'
Exec(@SQL);

从00:00到23:45返回96列

enter image description here

生成的代码

Select *
From (
        Select [SiteName]
              ,Col   = format(DateAdd(MINUTE,(DatePart(HOUR,[Time])*60) + ((DatePart(MINUTE,[Time]) / 15)*15),0),'HH:mm')
              ,Value = [Amount]
         From  Sales 
     ) A
Pivot (sum(Value) For [Col] in ([00:00],[00:15],[00:30],[00:45],[01:00],[01:15],[01:30],[01:45],[02:00],[02:15],[02:30],[02:45],[03:00],[03:15],[03:30],[03:45],[04:00],[04:15],[04:30],[04:45],[05:00],[05:15],[05:30],[05:45],[06:00],[06:15],[06:30],[06:45],[07:00],[07:15],[07:30],[07:45],[08:00],[08:15],[08:30],[08:45],[09:00],[09:15],[09:30],[09:45],[10:00],[10:15],[10:30],[10:45],[11:00],[11:15],[11:30],[11:45],[12:00],[12:15],[12:30],[12:45],[13:00],[13:15],[13:30],[13:45],[14:00],[14:15],[14:30],[14:45],[15:00],[15:15],[15:30],[15:45],[16:00],[16:15],[16:30],[16:45],[17:00],[17:15],[17:30],[17:45],[18:00],[18:15],[18:30],[18:45],[19:00],[19:15],[19:30],[19:45],[20:00],[20:15],[20:30],[20:45],[21:00],[21:15],[21:30],[21:45],[22:00],[22:15],[22:30],[22:45],[23:00],[23:15],[23:30],[23:45]) ) p

答案 1 :(得分:1)

这是一个不使用动态SQL的选项,而不是每行96列宽,每个时隙生成一行。首先,我从一个数据样本表开始。

create table #Sales
( SiteName nvarchar(1),
    SaleTime time,
    Amount decimal,
    BusinessDate Date );

insert into #Sales ( SiteName, SaleTime, Amount, BusinessDate )
values 
( 'A', '7:01:02', 20, '2017-01-02' ),
( 'A', '7:03:22', 25, '2017-01-02' ),
( 'A', '7:05:03', 33, '2017-01-02' ),
( 'A', '7:11:02', 55, '2017-01-02' ),
( 'A', '7:13:05', 46, '2017-01-02' ),
( 'A', '7:17:02', 21, '2017-01-02' ),
( 'A', '8:01:52', 18, '2017-01-02' ),
( 'A', '8:55:42', 7, '2017-01-02' ),
( 'A', '8:56:33', 7, '2017-01-02' ),
( 'A', '8:58:55', 31, '2017-01-02' );

And the query which I will explain shortly

select
        allTimes.TimeStart,
        allTimes.TimeEnd,
        coalesce( count(S.Amount), 0 ) as NumEntries,
        coalesce( sum( S.Amount), 0 ) as SumValues
    from
        ( select
                cast( DateAdd( minute, 15 * (timeSlots.Row -1), '2017-01-01' ) as time ) as TimeStart,
                cast( DateAdd( minute, 15 * timeSlots.Row, '2017-01-01' ) as time ) as TimeEnd
            from
                ( SELECT top 96
                        ROW_NUMBER() OVER(Order by AnyColumnInYourTable) Row
                    FROM     
                        AnyTableThatHasAtLeast96Rows ) timeSlots
        ) allTimes
            LEFT JOIN #Sales S
                on allTimes.TimeStart <= S.SaleTime
                AND S.SaleTime < allTimes.TimeEnd
            AND ( allTimes.TimeEnd < allTimes.TimeStart
                OR S.SaleTime <= allTimes.TimeEnd )
    group by
        allTimes.TimeStart,
        allTimes.TimeEnd

现在,解释......

首先,最内层的查询别名结果为“timeSlots”。这可以从任何表中查询至少有96个时间段的15分钟增量,并且不执行任何操作,只返回从1到96顺序编号的结果集。

现在我们有96行,我们到达下一个外部查询别名结果“allTimes”。这基本上是日期/时间数学,并添加15分钟间隔*无论“行”数值是创建所有时间段到96行。我已明确应用了开始和结束时间来应用&gt; =和&lt;。但是这个查询除了创建显式时隙外什么都不做。由于我将DATEADD()组件转换为TIME,因此我开始使用的固定“Date”值无关紧要 - 在本例中为2017-01-01。我所关心的只是时间本身。结果将像......

TimeStart    TimeEnd
00:00:00     00:15:00
00:15:00     00:30:00
00:30:00     00:45:00
...
23:30:00     23:45:00
23:45:00     00:00:00   -- This one is special for the JOIN clause for time

现在,LEFT JOIN ......这是一个非常棘手的

LEFT JOIN #Sales S
    on allTimes.TimeStart <= S.SaleTime
    AND S.SaleTime < allTimes.TimeEnd
    AND ( allTimes.TimeEnd < allTimes.TimeStart
        OR S.SaleTime <= allTimes.TimeEnd )

此处,左侧加入销售将始终允许每个时段位于最终结果集中。但是,特定销售适合哪个插槽?销售时间必须大于或等于起始的15分钟间隔......

和..

要么......结束时间小于开始时间(通过第二天早上23:45 - 00:00的时段),要么是下一个时段的开始时间。例如:08:30 - 8:45时间段实际上是8:44:xxxxx精度,但总是小于8:45。

通过这种方式,每个时间段有一行,我可以获得交易数量,交易总和,您甚至可以进行销售活动的平均值,最小值,最大值,以查找趋势。

答案 2 :(得分:1)

for(int i = 0; i < 3; i++){
    v3[i] = v1[i] + v2[i];
    printf("total: %d", v3[i]);
}

使用上面的代码获取96列,每天15分钟。

使用上述CTE加入销售表。

答案 3 :(得分:1)

这里递归CTE产生15分钟间隔24小时(96行)。

然后这个结果import Image def onInput_onStart(self): cam_input = ALProxy("ALVideoDevice") nameId = cam_input.subscribeCamera("Test_Cam", 1, 2, 13, 20) image = cam_input.getImageRemote(nameId) #captures an image w = image[0] #get the image width h = image[1] #get the image height pixel_array = image[6] #contains the image data result = Image.fromstring("RGB", (w, h), pixel_array) #the following line doesnt work result.save("C:\Users\Claudia\Desktop\NAO\Bilder\test.png", "PNG") cam_input.releaseImage(nameId) cam_input.unsubscribe(nameId) pass 编辑到子查询。在子查询LEFT JOIN中,每小时按15分钟的间隔进行分组。

结果,Amount对应的金额总和,从00:00:0000:00:00

00:14:59 =从00:15:0000:15:00

00:29:59 =从00:30:0000:30:00

00:44:59 =从00:45:0000:45:00

依旧每24小时

00:59:59

rextester demo