使用单个SQL执行此操作

时间:2020-03-06 15:00:44  来源:igfitidea点击:

我有一个看起来像这样的表:

这些行按CLNDR_DATE DESC排序。

我需要找到与突出显示的行相对应的CLNDR_DATE,换句话说:
找到最上面的一组行,其中EFFECTIVE_DATE不为空,
并返回该组最后一行的CLNR_DATE。

通常,我将打开一个游标并从上到下循环,直到在EFFECTIVE_DATE中找到NULL。然后,我知道我要查找的日期是在上一步中获得的CLNDR_DATE。

但是,我想知道是否可以通过单个SQL达到相同的效果?

解决方案

警告:绝不是DBA。 ;)

但是,这是一个未经测试的快速刺探:

SELECT min(CLNDR_DATE) FROM [TABLE]
WHERE (EFFECTIVE_DATE IS NOT NULL)
  AND (CLNDR_DATE > (
    SELECT max(CLNDR_DATE) FROM [TABLE] WHERE EFFECTIVE_DATE IS NULL
  ))

假设我们要第一个CLNDR_DATE加上EFFECTIVE_DATE,最后一个不带。

如果我们想要第一个with之后的第一个with,则将子查询更改为使用min()而不是max()。

该记录集的第一个结果就是我们要寻找的。根据数据库,我们可能只能使用LIMIT或者TOP返回此行。

SELECT CLNDR_DATE 
FROM TABLE
WHERE CLNDR_DATE > (SELECT MAX(CLNDR_DATE)
                    FROM TABLE 
                    WHERE EFFECTIVE_DATE IS NOT NULL)
ORDER BY CLNDR_DATE

当我们在Oracle环境中时,可以使用分析功能(http://www.orafaq.com/node/55),这些功能非常强大,可以执行我们所要求的查询。

我认为使用标准SQL是不可能的,但是也许某些SQL专家会提出一些不错的解决方案。

使用Oracle的分析功能(未经测试)

select *
from
(
  select 
    clndr_date, 
    effective_date, 
    lag(clndr_date, 1, null) over (order by clndr_date desc) prev_clndr_date
  from table
)
where effective_date is null

lag(clndr_date,1,null)over(按clndr_date desc排序)返回前一个clndr_date,如果这是第一行,则使用null。

(编辑:固定顺序)