2014-03-03 74 views
2

我想知道是否只能使用SQL生成销售数据的运行总计或总计时间块。可以使用SQL计算时间带的累积数据吗?

比方说,我有一个简单的表,记录销售额和他们发生的时间。

ID | Timestamp   | Amount 
1 | 2014-03-04 09:00:00 | 25.00 
2 | 2014-03-04 09:02:25 | 15.00 
3 | 2014-03-04 09:13:00 | 5.00 
4 | 2014-03-04 09:16:11 | 17.50 
5 | 2014-03-04 09:28:18 | 44.50 
... 

我可以很容易地计算出一天的总销售额与像查询:

SELECT sum(Amount) from Sales 
WHERE Timestamp BETWEEN '2014-03-04 00:00:00' AND '2014-03-04 23:59:59' 

但我想所有的计算过程中的每个(说)15分钟内销售的金额获得结果,如:

08:45 | 0.00 
09:00 | 45.00 
09:15 | 62:00 
... 

和累积运行总计为每个(比如说)15分钟内,以产生像的结果:

08:45 | 0:00 
09:00 | 40.00 
09:15 | 107:00 
... 

我可以编写一个简单的程序或使用电子表格来实现给定原始数据的这两个结果,但是我想知道如何使用SQL来完成它。可能吗?如果是这样,怎么样?

编辑:如果可能,DB-agnostic解决方案将是首选。目前我使用SQL Server。

+0

没有与数据库无关的方式来处理分箱时间戳。 –

回答

0

在SQL Server 2012中,您可以使用累积求和窗口函数来执行此操作。您也可以在接近在多个数据库的工作方式的时隙:

select timeslot, 
     sum(amount) as amount, 
     sum(sum(amount)) over (order by timeslot) as cumamount 
from (select t.*, 
      (cast('2014-03-04 00:00:00' as datetime) + 
       cast(("timestamp" - cast('2014-03-04 00:00:00' as datetime))*24*4 as int)/(24.0*4) 
      ) as timeslot 
     from table t 
    ) t 
where Timestamp between '2014-03-04 00:00:00' and '2014-03-04 23:59:59' 
group by timeslot; 

timeslot计算背后的想法是采取timestamp,有一天午夜之间的差异。这给出了两个日期之间的天数(分数)。然后用24乘以小时乘以4乘以15分钟的间隔,并给出从某日的午夜开始的15分钟的间隔数。通过转换为整数并添加回原始日期来截断此值。这全部在子查询中完成,因此可以重复计算。

这种方法适用于很多数据库,尽管确切的表达可能存在一些细微差别。 datetime的格式将是数据库特定的。

其余的就是使用累加和函数。如果你没有这个,那么你可以使用相关的子查询。

0

我没有sol首次请求。 (总计每个“Timeslot”类型的查询) 但我确实有第二个请求。 (每个“Timeslot”的累积运行总数)

AS Gordon在SQL Server 2012中提到,这非常简单。 但是,我提供了一个可以在SQL 2005之后完成的旧方法。

此外,解决方案并非100%与数据库无关,但更容易从SQL-SERVER转换为ORACLE或DB2或其他任何东西。

在进行实际查询之前,请查看我创建的函数,以便在给出两个日期范围时给我一个TimeSlot值。 UFN to GET TIMESLOT Values

请注意,该功能是按插槽类型在不同粒度级别创建的。小时,分钟,秒等....你可以创建新的,只要你喜欢。

在下面的示例查询中,我选择了11秒的时隙。

检查结果在这里。 Sample Output

DECLARE @dt TABLE 
    (
     RowID    INT IDENTITY NOT NULL 
     ,LastModified  DATETIME2(2) NOT NULL 
     ,Amount    INT NOT NULL DEFAULT 0 
    ) 

    INSERT INTO @dt(LastModified, Amount) 
       SELECT '2014-03-04 00:00:00.00', 10 
    UNION ALL SELECT '2014-03-04 00:00:05.00', 10 
    UNION ALL SELECT '2014-03-04 00:00:10.00', 10 
    UNION ALL SELECT '2014-03-04 00:00:15.00', 10 
    UNION ALL SELECT '2014-03-04 00:00:20.00', 10 
    UNION ALL SELECT '2014-03-04 00:00:25.00', 10 
    UNION ALL SELECT '2014-03-04 00:00:30.00', 10 
    UNION ALL SELECT '2014-03-04 00:00:35.00', 10 
    UNION ALL SELECT '2014-03-04 00:00:40.00', 10 
    UNION ALL SELECT '2014-03-04 00:00:45.00', 10 
    UNION ALL SELECT '2014-03-04 00:00:50.00', 10 


    DECLARE @DatePart sysname 
      ,@SlotValue INT 
      ,@MinDt DATETIME2(2) 
      ,@MaxDt DATETIME2(2) 

    SET @SlotValue = 11 
    SELECT @MinDt=MIN(LastModified) 
      ,@MaxDt=MAX(LastModified) 
    FROM @dt 

    ;WITH AllDt(RowID,timeslot,amount) 
    AS 
    (
     SELECT CAST (ROW_NUMBER() OVER (ORDER BY COALESCE(t1.TimeSlot,t2.LastModified)) AS INT) RowID 
       ,COALESCE(t1.TimeSlot,t2.LastModified) 
       ,ISNULL(t2.Amount,0) AS Amount 
     FROM dbo.ufn_utl_timeslotBySecond(@SlotValue,@MinDt,@MaxDt) t1 
     FULL OUTER JOIN @dt t2 
      ON t1.TimeSlot=t2.LastModified 
    ) 
    , 
    RCTE1(RowID,timeslot,amount) 
    AS 
    (
     SELECT RowID 
       ,timeslot 
       ,Amount 
     FROM AllDt 
     WHERE RowID=1 
     UNION ALL 

     SELECT dt.RowID,dt.TimeSlot,CAST(dt.Amount+t3.amount AS INT) AS amount 
     FROM ALLDt dt 
     JOIN RCTE1 t3 
      ON dt.RowID=t3.RowID+1 
    ) 
    SELECT * 
    FROM RCTE1 
    ORDER BY TimeSlot