2011-12-21 67 views
0

請原諒,如果標題不夠描述。
這裏是我的問題情景:查詢有條件地計算數據與以前的記錄

我有一個表有以下的列(由):

oid rev state time 
1  0 S T1 
2  0 S T2 
1  0 A T3 
2  0 A T4 
2  1 MS T5 
2  1 MA T6 
2  1 M T7 
2  2 MS T8 
2  2 M T9 

時間列是VARCHAR(含日期/時間)
我需要找到從狀態爲每個訂單採取轉變到狀態時間 - 有效的狀態轉換的定義如下:

S->A 
MS->MA 
MS-M 

(即,過渡可以是從提交給ACK,修改。 - 提交修改 - 確認或修改 - 提交修改) 和MS可以轉換到MA然後轉換到M,但是我只對從MS到MA的轉換感興趣。

在上述:

oid 1 transitioned from S to A. 
oid 2 changed from S to A (rev 0) 
oid 2 changed from MS to MA (rev 1) - here we don't want to consider transition to M 
oid 2 changed from MS to M (rev 2) 

所以查詢輸出應如下(timeTaken將是的毫秒):

oid rev timeTaken state 
1 0 (T3-T1) A 
2 0 (T4-T2) A 
2 1 (T6-T5) MA 
2 2 (T9-T8) M 

所以,如果當前記錄狀態是MA或M的時間差只有在先前的記錄狀態是MS時才需要計算(假設這是按照oid,rev,time命令的)。如果當前記錄狀態是M,則如果先前記錄狀態是MA,則跳過。

有沒有辦法在mysql中使用sql查詢來做到這一點。任何指針都會有幫助。謝謝。

====
該表有時間作爲主鍵。

我有這個疑問得到它以正確的方式排序(如果它以任何方式幫助)

從訂單的訂單ID,時間選擇OID,轉速,狀態,時間,轉速

這將得到:

OID轉狀態時
1 0 S T1
1 0 A T3
2 0 S T2
2 0 T4
2 1 MS T5
2 1 MA T6
2 1M的T7
2 2 MS T8
2 2M的T9

會幫助呢?

+0

問題,如果你的原始表有某種自動遞增的id,這可能會容易得多。可以? – 2011-12-22 03:53:15

+0

,我們可以假設時間被分類? – 2011-12-22 04:24:54

+0

我有這個查詢,以正確的方式得到它: – 2011-12-22 17:53:01

回答

0

嗯,我認爲這是你應該做的代碼,而不是你的數據庫。

我可以想出一種用SQL做這件事的方法,但它有點複雜。 它是這樣的。假設您的原始表格是t1

  1. 創建包含每個oid,rev中所有可能轉換的視圖。

    create view transitions as 
        select a.oid, a.rev, a.state as state_from, b.state as state_to, 
          a.time as time_from, b.time as time_to 
        from t1 as a, t1 as b 
        where a.oid=b.oid 
         and a.rev=b.rev 
         and a.time<b.time; 
    
    
    +------+------+------------+----------+-----------+---------+ 
    | oid | rev | state_from | state_to | time_from | time_to | 
    +------+------+------------+----------+-----------+---------+ 
    | 1 | 0 | S   | A  |  T1 |  T3 | 
    | 2 | 0 | S   | A  |  T2 |  T4 | 
    | 2 | 1 | MS   | MA  |  T5 |  T6 | 
    | 2 | 1 | MS   | M  |  T5 |  T7 | 
    | 2 | 1 | MA   | M  |  T6 |  T7 | 
    | 2 | 2 | MS   | M  |  T8 |  T9 | 
    +------+------+------------+----------+-----------+---------+ 
    
  2. 注:此步驟是必要的,但用於教育目的!)修剪出在哪裏時間不連續的一切。它通過採取將該行與最低time_to每個time_from(因此它需要T5->T6,而不是T5->T7

    select a.* 
    from transitions as a 
    join (
        select oid, rev, time_from, min(time_to) as time_to 
        from transitions 
        group by time_from 
        ) as b 
        on a.oid=b.oid and a.rev=b.rev 
        and a.time_from=b.time_from and a.time_to=b.time_to; 
    
    +------+------+------------+----------+-----------+---------+ 
    | oid | rev | state_from | state_to | time_from | time_to | 
    +------+------+------------+----------+-----------+---------+ 
    | 1 | 0 | S   | A  |  T1 |  T3 | 
    | 2 | 0 | S   | A  |  T2 |  T4 | 
    | 2 | 1 | MS   | MA  |  T5 |  T6 | 
    | 2 | 1 | MA   | M  |  T6 |  T7 | 
    | 2 | 2 | MS   | M  |  T8 |  T9 | 
    +------+------+------------+----------+-----------+---------+ 
    
  3. 現在你只需要選擇time_from-time_to其中state_fromstate_to是那些你感興趣的過渡。所以第2步是沒有必要的,您可以與之前的查詢結合本(步驟2中的唯一的新東西是,上和/或/或位):

    select a.oid,a.rev,a.state_to as state,a.time_to-a.time_from as timeTaken 
    from transitions as a 
    join (
        select oid, rev, time_from, min(time_to) as time_to 
        from transitions 
        group by time_from 
        ) as b 
        on a.oid=b.oid and a.rev=b.rev 
        and a.time_from=b.time_from and a.time_to=b.time_to 
    and ( (a.state_from='S' and a.state_to='A') 
        or (a.state_from='MS' and a.state_to='MA') 
        or (a.state_from='MS' and a.state_to='M') 
        ); 
    
    +------+------+-------+-----------+ 
    | oid | rev | state | timeTaken | 
    +------+------+-------+-----------+ 
    | 1 | 0 | A  | T3-T1 | 
    | 2 | 0 | A  | T4-T2 | 
    | 2 | 2 | M  | T6-T5 | 
    | 2 | 1 | MA | T9-T8 | 
    +------+------+-------+-----------+ 
    

因此,總之,請執行步驟1)一次創建視圖,然後在每次需要執行計算時執行步驟3)。

我敢打賭,有一個更有效的方式來做到這一點 - 這不是我的特長。 我認爲做join比將其全部移到where條款便宜,創建視圖只是一次性成本。

+0

這真的有幫助!謝謝!!! – 2011-12-23 20:31:06

相關問題