2014-03-03 75 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