2014-08-28 133 views
1

我在策略表中有策略信息。每行代表特定時間的策略狀態(時間存儲在updated_on列中)。每行都屬於策略迭代(多個策略行可以屬於單個策略迭代)。我想查看一個策略迭代中行與行之間的狀態變化。將以前的行子查詢轉換爲MySQL中的連接

的策略表:

CREATE TABLE `policy` (
    `policy_id` int(11) unsigned NOT NULL AUTO_INCREMENT, 
    `policy_iteration_id` int(10) unsigned NOT NULL, 
    `policy_status_id` tinyint(3) unsigned NOT NULL, 
    `updated_on` datetime NOT NULL, 
    PRIMARY KEY (`policy_id`), 
    KEY `policy_iteration_idx` (`policy_iteration_id`), 
    KEY `policy_status_updated_idx` (`policy_status_id`,`updated_on`) 
) ENGINE=InnoDB DEFAULT CHARSET=latin1; 

我希望能夠傳遞一個日期範圍和「從」狀態和「到」的狀態,併爲「到」行返回策略數據。因此,在僞代碼中,我需要按策略迭代進行分組,查找滿足數據範圍和「到」狀態的行,然後查看該策略迭代中的上一行,以查看它是否具有「from」狀態。如果是,請返回「到」行的信息。

這是我想出了查詢:

SELECT 
    pto.policy_iteration_id, 
    pto.policy_id, 
    pto.updated_on, 
FROM 
    policy AS pto 
WHERE 
    pto.updated_on >= $from_date AND 
    pto.updated_on <= $to_date AND 
    pto.policy_status_id = $to_status_id AND 
    $from_status_id = 
    (SELECT 
     pfrom.policy_status_id 
    FROM 
     policy AS pfrom 
    WHERE 
     pfrom.policy_iteration_id = pto.policy_iteration_id AND 
     pfrom.policy_id < pto.policy_id 
    ORDER BY 
     pfrom.policy_id DESC 
    LIMIT 
     1); 

這個查詢工作,但其原因在於每一行要執行的子查詢的效率非常低。我想通過使用子查詢連接來提高效率,但我無法弄清楚。

任何幫助,將不勝感激。謝謝!

更新#1

爲了幫助解釋什麼,我試圖做的,這裏是一個示例數據集中:

+-----------+---------------------+------------------+---------------------+ 
| policy_id | policy_iteration_id | policy_status_id | updated_on   | 
+-----------+---------------------+------------------+---------------------+ 
| 323705 |    27230 |    6 | 2014-08-01 10:27:11 | 
| 325028 |    27230 |    2 | 2014-08-01 17:12:28 | 
| 323999 |    27591 |    2 | 2014-08-01 12:07:31 | 
| 324008 |    27591 |    6 | 2014-08-01 12:10:23 | 
| 325909 |    27591 |    2 | 2014-08-02 14:59:12 | 
| 327116 |    29083 |    6 | 2014-08-04 12:09:16 | 
| 327142 |    29083 |    6 | 2014-08-04 12:19:00 | 
| 328067 |    29083 |    2 | 2014-08-04 17:58:41 | 
| 327740 |    29666 |    3 | 2014-08-04 16:16:55 | 
| 327749 |    29666 |    3 | 2014-08-04 16:19:01 | 
+-----------+---------------------+------------------+---------------------+ 

現在,如果我運行查詢,其中FROM_DATE =「2014-08- 02 00:00:00' ,TO_DATE = '2014年8月5日00:00:00',from_status = 6和to_status = 2時,結果應該是:

+-----------+---------------------+------------------+---------------------+ 
| policy_id | policy_iteration_id | policy_status_id | updated_on   | 
+-----------+---------------------+------------------+---------------------+ 
| 325909 |    27591 |    2 | 2014-08-02 14:59:12 | 
| 328067 |    29083 |    2 | 2014-08-04 17:58:41 | 
+-----------+---------------------+------------------+---------------------+ 

這兩行具有與行在規定的時間段內所選的「to_status」爲2並且其前一行的「from_status」爲6.

我不相信用policy_iteration_id的GROUP BY加入MAX策略ID將執行該任務,因爲那樣會返回最近的行,而不是具有「to_status」的行之前的行。

任何進一步的幫助,將不勝感激。謝謝!

回答

1

您可以使用max from.policy_id where from.policy_id < to.policy_id來幫助獲取上一行作爲集合。

select 
     p.policy_iteration_id, 
     p.policy_id, 
     p.updated_on 
from 
    policy f 
     inner join (
    select 
     p.policy_iteration_id, 
     p.policy_id, 
     p.updated_on, 
     max(f.policy_id) as prev_policy_id 
    from 
     policy p 
      inner join 
     policy f 
      on f.policy_iteration_id = p.policy_iteration_id and 
       f.policy_id < p.policy_id 
    where 
     p.updated_on >= $from_date and 
     p.updated_on <= $to_date and 
     p.policy_status_id = $to_status_id 
    group by 
     p.policy_iteration_id, 
     p.policy_id, 
     p.updated_on 
) p 
     on p.prev_policy_id = f.policy_id 
where 
    f.policy_status_id = $from_status_id 

在具有窗口函數的數據庫中,實現此目的有更簡單的方法。

Example SQLFiddle

+0

+1用於窗口功能。 – paqogomez 2014-08-28 22:29:19

+0

不僅窗口功能; IIUC直接加入自己就足夠了。 – wildplasser 2014-08-28 22:57:12

+0

@wildplasser http://sqlfiddle.com/#!2/b0e9bf/6有一個以前的(現在刪除的)解決方案使用自加入,OPs解決方案和我的。你能糾正自己的加入嗎? – Laurence 2014-08-28 23:23:38