选择内部查询中的最大值<外部查询中的另一个

时间:2012-03-29 22:30:05

标签: sql audit hibernate-envers audit-tables

我有两个审核表:Trip_aud和Event_aud。它们是在Envers中创建的,但我用SQL查询它们。它们与域表基本相同,除了修订值,每次有更改并且在审计表中插入一些元组时,该值会递增。

当旅行从某个状态(PLANNING - > EXECUTING)发生变化时,我会存储其当前版本,所以之后我可以比较执行的内容(比如说,离开时间)和计划。这些事件(离开,停止,等待......)存储在Event中,并带有指向Trip的指针。事件也经过审核。

Envers的工作方式类似于CVS系统:如果我查询给定修订版的某个元素,它会搜索最大修订版小于给定修订版的元组。我感兴趣的修订版是Trip上的版本,当它改变状态时存储。 如何从给定修订中的旅行中选择所有事件?

这是表格的样子。 org_rev是状态更改的行程修订版。

Trip_aud
id  | rev | status   | org_rev | other columns...
----|-----|----------|---------|---------------
 1  |  1  |CREATED   |  NULL   |
 1  |  2  |OPTIMIZING|  NULL   |
 1  |  3  |PLANNED   |  NULL   |
 1  | ... |   ...    |  NULL   |
 1  |  44 |EXECUTING |   44    |
 1  |  58 |FINISHED  |   44    |

Event_aud
id  | trip_id | rev | start_time | other columns...
----|---------|-----|------------|---------------
 1  |    1    |  1  | 02:35:12   |
 2  |    1    |  1  | 03:14:84   |
 3  |    1    |  1  | 12:31:02   |
 1  |    1    |  2  | 04:00:00   |
 2  |    1    |  5  | 03:00:15   |
 2  |    1    |  10 | 05:49:59   |
 1  |    1    |  40 | 06:00:00   |
 1  |    1    |  58 | 06:07:39   |

如果我想要修改3的旅行和活动,我会

Trip_aud
id  | rev | status   | org_rev | other columns...
----|-----|----------|---------|---------------
 1  |  3  |PLANNED   |  NULL   | ...

 Event_aud
id  | trip_id | rev | start_time | other columns...
----|---------|-----|------------|---------------
 1  |    1    |  2  | 04:00:00   |
 2  |    1    |  1  | 03:14:84   |
 3  |    1    |  1  | 12:31:02   |

在修订版44中,当计划完成时,它是

Trip_aud
id  | rev | status   | org_rev | other columns...
----|-----|----------|---------|---------------
 1  |  44 |EXECUTING |   44    |

Event_aud
id  | trip_id | rev | start_time | other columns...
----|---------|-----|------------|---------------
 1  |    1    |  40 | 06:00:00   |
 2  |    1    |  10 | 05:49:59   |
 3  |    1    |  1  | 12:31:02   |

我已经进行了以下查询来比较计划和执行,但它没有返回任何内容!它在EVENT_AUD中进行自我加入,驱逐仅在其修订顺序上有所不同的元组重复项,并尝试在旅行时选择小于rev的最大值org_rev

 select t.id, planned.start_time, realized.start_time
 from 
     TRIP t
     inner join EVENT realized on realized.trip_id = t.id
     inner join EVENT_AUD planned on planned.id = realized.id
 where
     planned.id in
     (
         select ea1.id
         from
             EVENT_AUD ea1
             inner join EVENT_AUD ea2 on ea1.id = ea2.id
         where
            ea1.rev > ea2.rev
         group by ea1.id
         having max(ea1.rev) < t.org_rev
    )
    and t.id = {something given outside}

奇怪的是,如果我用44替换t.org_rev,它就可以了!我究竟做错了什么?

感谢您的帮助!

META:是否需要在CSV,XML,INCLUDE INTO等中提供一些小数据库示例,以便人们可以测试我要求的SQL?我怎么能附上这个问题?

1 个答案:

答案 0 :(得分:1)

我认为你也需要在旅行ID上加入ea1和ea2,因为这样max会给所有事件带来最大的转速。事件和event_aud之间也缺少此连接。相关子查询需要

where ea1.trip_id = t.id

<强>更新

我不理解计划中的逻辑(选择...)所以我把它改为不存在:

 select t.id TripID, 
        planned.id pid, 
        planned.rev, 
        planned.start_time pst, 
        realized.start_time rst
 from 
     TRIP t
     inner join EVENT realized 
        on realized.trip_id = t.id
     inner join EVENT_AUD planned 
        on planned.id = realized.id
           and realized.trip_id = planned.trip_id
        -- Eliminate higher revisions
           and planned.rev < t.org_rev
 where not exists (select null 
             from event_aud ea
            where ea.trip_id = planned.trip_id
              and ea.id = planned.id
        -- Eliminate higher revisions
              and ea.rev < t.org_rev
        -- If there is higher revision than current not exists evaluates to false
              and ea.rev > planned.rev)
    and t.id = 1
order by 1, 2

完整查询位于Sql Fiddle