2009-10-20 51 views
2

我有一个需求,我需要生成一个关于当前软件项目的报告。其中两列是最新里程碑的日期和之前的里程碑的日期。很显然,里程碑存储在交易表中,所以我们可以为每个项目设立多个里程碑。选择单行交易

我已经得到了到这里为止,但现在我有问题:

select proj.* 
from zsof_projects proj 
join zsof_milestones current_milestone on current_milestone.product_id = proj.id 
join zsof_milestones last_milestone on last_milestone.product_id = proj.id 
join (
     select product_id, max(actual_date) maxDate 
     from zsof_milestones 
     group by product_id 
     ) a on a.product_id = current_milestone.product_id and a.maxDate = current_milestone.actual_date 
join (
     select mile.product_id, max(actual_date) maxDate 
     from zsof_milestones mile 
     join (
       select product_id, max(actual_date) maxDate 
       from zsof_milestones 
       group by product_id 
       ) a on a.product_id = mile.product_id and mile.actual_date < a.maxDate 
     group by mile.product_id 
     ) b on b.product_id = last_milestone.product_id and b.maxDate = last_milestone.actual_date 
order by proj.id; 

我的问题是,并非所有的项目都会有一个最新的里程碑,而不是所有的项目都会有超过一个里程碑。我尝试过左连接,但是后来我为每个项目取回多行(这是我需要避免的)。

我使用的是Oracle 10,所以如果有什么我可以在PL/SQL中使用的,我也会这样做。

回答

4

使用分析:)

SELECT v.* 
    FROM (SELECT proj.*, actual_date, 
       MAX(actual_date) over(PARTITION BY ms.product_id) last_milestone, 
       lag(actual_date) over(PARTITION BY ms.product_id 
            ORDER BY actual_date) previous_milestone 
      FROM zsof_projects proj 
      LEFT JOIN zsof_milestones ms ON ms.product_id = proj.id) v 
WHERE last_milestone = actual_date 
    OR (actual_date IS NULL AND last_milestone IS NULL) 

更新:我改变了连接成一个LEFT JOIN的情况下,一个项目没有一个里程碑。

+0

谢谢!这很好。我还没有看到你在那里使用的一些功能,所以看起来我有一些阅读要做。 – 2009-10-20 17:01:58