我在策略表中有策略信息。每行代表特定时间的策略状态(时间存储在updated_on列中)。每行属于策略迭代(多个策略行可以属于单个策略迭代)。我想查看策略迭代中从行到行的状态更改。
政策表:
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-08-05 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”的行之前的行。< / p>
任何进一步的帮助将不胜感激。谢谢!
答案 0 :(得分: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
在具有窗口函数的数据库中,有更简单的方法可以实现此目的。