2014-03-31 74 views
1

我有一個數據庫,其中包含數百萬行跟蹤訂單在整個系統中的進度的信息行。從一個端到另一端,訂單可以通過2至20個系統的任何地方。這段旅程的每一部分都將記錄在數據庫中,例如,將查詢重組爲按月份/年份組

ORDER ID  SOURCE  DESTINATION  TIMESTAMP 
10    Sys 1   Sys 2   01-Jan-14 
10    Sys 2   Sys 3   01-Jan-14 
10    Sys 3   Sys 4   03-Jan-14 
10    Sys 4   Sys 5   07-Jan-14 

時間戳記錄時的順序該系統。

我有一個查詢我寫來確定每個訂單的長度:

Select ORDERID, 1 + TRUNC(MAX(TIMESTAMP)) - TRUNC(MIN(TIMESTAMP)) 
from DATABASE GROUP BY ORDERID 

這工作正常,併爲上述順序將產生7天。當我在數據庫中的每個元組上運行這個查詢時,我得到數據庫中每個單獨訂單的平均端到端訂單進度時間。然後,我可以使用所有這些個人總數來查找總體平均訂單時間。

這一切都很好,但我現在希望能夠將此分解爲單個月/年配對,以便我可以有效地查看系統中平均時間長度是增加還是減少了給定月。

我對SQL相當缺乏經驗,我真的不知道從哪裏開始。我怎麼能寫一個查詢,以追蹤任何訂單的開始日期,並查看它在系統中停留多久,產生系統每月/年組合的總天數?

樣本數據

目前,上述查詢會產生一系列的元組是這樣的:

Order Id Days in System 
0145240 1 
10000 1 
10001 1 
10003 130 
10004 3 
10007 1 
10008 13 
10009 1 
10010 1 

然後我就可以找到所有這些信息的平均值。我真正喜歡的是能夠做到這樣的事情:

ORDER ID  SOURCE  DESTINATION  TIMESTAMP 
10    Sys 1   Sys 2   01-Jan-14 
10    Sys 2   Sys 3   01-Jan-14 
10    Sys 3   Sys 4   03-Jan-14 
10    Sys 4   Sys 5   07-Jan-14 
11    Sys 1   Sys 2   01-Feb-14 
11    Sys 2   Sys 3   03-Mar-14 
12    Sys 1   Sys 2   04-Mar-14   
12    Sys 2   Ssy 3   05-Mar-14 
13    Sys 1   Sys 2   07-Mar-14 
13    Sys 2   Sys 3   14-Mar-14 

想象一下,以上所有都是完成的訂單。

OrderID 10:花了7天時間從頭到尾。
OrderID 11:從頭到尾花了31天時間。
OrderID 12:花了2天時間從頭到尾。
OrderID 13:花了8天時間從頭到尾。

OrderId 10是1月份的唯一訂單,OrderID 11僅在2月訂購,OrderID 12和13都在3月份發佈。因此,理想情況下,我想設計的查詢會產生如下:

Jan 2014: Average = 7 
Feb 2014: Average = 31 
Mar 2014: Average = 5 (i.e. (2 + 8)/2) 
+0

你能舉些簡單的例子,有數據請以清除任何歧義。謝謝 –

回答

1

你可以看看分析函數,但一個相當簡單的方法是添加'開始'日期(這有點令人困惑,因爲它似乎是第一個系統的訂單離開的時間戳,而不是當它到達那裏):

select orderid, min(timestamp) as first_seen, 
    1 + trunc(max(timestamp)) - trunc(min(timestamp)) as duration 
from database 
group by orderid 
order by orderid; 

與可能給你一些額外的數據:

ORDERID FIRST_SEEN      DURATION 
---------- ---------------------------- ---------- 
     10 01-JAN-14 09.00.00.000000000   7 
     11 01-JAN-14 09.00.00.000000000   2 
     12 31-JAN-14 09.00.00.000000000   3 
     13 01-FEB-14 09.00.00.000000000   2 

然後,您可以使用它作爲通過在當月的第一天分組的子查詢和平均'第一次看到'日期:

select trunc(first_seen, 'MM') as month, 
    avg(duration) as duration 
from (
    select orderid, min(timestamp) as first_seen, 
    1 + trunc(max(timestamp)) - trunc(min(timestamp)) as duration 
    from database group by orderid 
) 
group by trunc(first_seen, 'MM') 
order by trunc(first_seen, 'MM'); 

MONTH  DURATION 
--------- ---------- 
01-JAN-14   4 
01-FEB-14   2 

SQL Fiddle。調用表'數據庫'有點令人困惑,因爲它是一個keyword(雖然不保留,所以它是合法的)。並且調用一個'timestamp'列也有點奇怪,特別是如果它實際上是date而不是timestamp--目前還不清楚你的實際表有哪些。但是,因爲您已更改發佈的名稱,所以這實在是太沒有意義了。

或者with your expanded sample data

ORDERID FIRST_SEEN      DURATION 
---------- ---------------------------- ---------- 
     10 01-JAN-14 00.00.00.000000000   7 
     11 01-FEB-14 00.00.00.000000000   31 
     12 04-MAR-14 00.00.00.000000000   2 
     13 07-MAR-14 00.00.00.000000000   8 

MONTH  DURATION 
--------- ---------- 
01-JAN-14   7 
01-FEB-14   31 
01-MAR-14   5 
+0

謝謝你這絕對美妙的解決方案。僅供參考,我更改了所有內容的默認字段名稱。它不是_really_所謂的數據庫或時間戳。 –

2

在一個月明智的基礎

Select ORDERID, 
     to_char(to_date(Timestamp, 'DD-MM-YYYY'), 'Month'), 
     1 + TRUNC(MAX(TIMESTAMP)) - TRUNC(MIN(TIMESTAMP)) as duration 
from DATABASE GROUP BY ORDERID, to_char(to_date(Timestamp, 'DD-MM-YYYY'), 'Month') 
Order By ORDERID,duration 

同樣可以從時間戳日期欄和組由訂單ID和年extarct年跟蹤每個訂單ID的年度持續時間。

+0

你不需要'to_date(timestamp,...)',而且如果你的NLS_DATE_FORMAT不匹配'DD-MON-YYYY',事實上會出錯。 –

+0

okyes ...我在sql服務器上工作,並從日期抽取月份的月份。 –