根据条件获取最新行

Get the latest row based on condition

我有一个table material -- HERE IS THE FIDDLE

+--------+-----+-------------------+----------------+-----------+          
| ID     | REV | name              | Description    | curr      |
+--------+-----+-------------------+----------------+-----------+
| 211-32 | 001 | Screw 1.0         | Used in MAT 1  | READY     |
| 211-32 | 002 | Screw 2 plus      | can be Used-32 | WITHDRAWN |
| 212-41 | 001 | Bolt H1           | Light solid    | READY     |
| 212-41 | 002 | BOLT H2+Form      | Heavy solid    | READY     |
| 101-24 | 001 | HexHead 1-A       | NOR-1          | READY     |
| 101-24 | 002 | HexHead Spl       | NOR-22         | READY     |
| 423-98 | 001 | Nut Repair spare  | NORM1          | READY     |
| 423-98 | 002 | Nut Repair Part-C | NORM2          | WITHDRAWN |
| 423-98 | 003 | Nut SP-C          | NORM2+NORM1    | NULL      |
| 654-01 | 001 | Bar               | Specific only  | WITHDRAWN |
| 654-01 | 002 | Bar rod-S         | Designed+Spe   | WITHDRAWN |
| 654-01 | 003 | Bar OPG           | Hard spec      | NULL      |
+--------+-----+-------------------+----------------+-----------+

这里每个ID可以有多个修改。我想采用最新修订 (即 001,002,003 等中的最高版本,)。但是,如果最新版本将 curr 作为 NULL(string) 或 WITHDRAWN,那么我将采用之前的版本及其相应的值。如果即使 currNULLWITHDRAWN 我也必须再次转到以前的修订版。如果所有修订版都有相同的问题,那么我们可以忽略它。所以预期的输出是

+--------+-----+------------------+---------------+-------+
| ID     | REV | name             | Description   | curr  |
+--------+-----+------------------+---------------+-------+
| 211-32 | 001 | Screw 1.0        | Used in MAT 1 | READY |
| 212-41 | 002 | BOLT H2+Form     | Heavy solid   | READY |
| 101-24 | 002 | HexHead Spl      | NOR-22        | READY |
| 423-98 | 001 | Nut Repair spare | NORM1         | READY |
+--------+-----+------------------+---------------+-------+

我试过下面的代码,但我不确定如何进行以前的修改。

with cte as (
select *,dense_rank() over (partition by id order by rev desc) as DR ,
lead(curr) over (partition by id order by rev desc) LEAD_CURR
from material )
select * from cte where DR = 1 and curr='READY'
union all
select * from cte where LEAD_CURR='READY' and DR=2
union all
select * from cte where LEAD_CURR='READY' and DR=3

这听起来像是过滤然后计算行号:

select m.*
from (select m.*,
             row_number() over (partition by id order by rev desc) as seqnum
      from material m
      where curr is not null and curr not in ( 'WITHDRAWN', 'NULL' ) 
     ) m
where seqnum = 1;

您也可以使用相关子查询来做到这一点:

select m.*
from material m
where m.rev = (select max(m2.rev)
               from material m2
               where m2.id = m.id and
                     curr is not null and curr not in ( 'WITHDRAWN', 'NULL' ) 
              );

Here 是一个 db<>fiddle.

注意:将字符串 'NULL' 存储在列中是非常不传统的,因为这很容易与 SQL“常量”NULL.

此外,您的问题特别提到了 'WITHDRAWN'NULL,但没有说明其他允许的值。显然,上述查询中的逻辑可能等同于 curr = 'READY',您可以使用它。以上逻辑符合你对问题的描述。