如何根据特定编号的条件更改记录的状态

时间:2018-11-30 12:06:21

标签: sql oracle

我在名为t1的表中具有以下数据,

number  status  date
100718  A       01-DEC-08
100718  A       14-NOV-16
10110   I       14-NOV-16
10110   A       19-SEP-18
10110   A       27-NOV-18
102965  I       01-DEC-08
102965  I       01-DEC-09

现在,如果某个特定号码的任何状态为A(有效),那么我需要将该号码的状态设置为A,并将日期设置为最近的有效日期;如果某个特定号码的所有状态I(无效),则我需要将特定编号和最近的无效日期设置为“我”。

我想要如下所示的数据,

number  status  date
100718  A       14-NOV-16
100718  A       14-NOV-16
10110   A       27-NOV-18
10110   A       27-NOV-18
10110   A       27-NOV-18
102965  I       01-DEC-09
102965  I       01-DEC-09

请帮助我完成工作。谢谢:)

2 个答案:

答案 0 :(得分:1)

这可以使用MINLAST_VALUE分析函数来实现。

SELECT c_number,
       status,
       LAST_VALUE(c_date) OVER(
            PARTITION BY c_number,status ORDER BY c_date
            ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING
       ) AS latest_dt
FROM (
     SELECT c_number,
            CASE WHEN MIN (status) OVER( PARTITION BY c_number ) = 'A' THEN 'A'
                 ELSE status END --NVL(status,'I') or default for other than A & I
       AS status,
            c_date
     FROM t1
) s
ORDER BY status,
         latest_dt;

基本上,子查询检查组中是否至少存在一个“ A”,并依赖于状态“ A”是按字母顺序排列的最小状态的事实。如果您还有其他小写状态,则可以通过在状态上添加CASE来更改UPPER()条件。

带有windowing子句的LAST_VALUE函数获取所有日期(UNBOUNDED PRECEDING AND UNB...)中从子查询派生的c_number和status的每种组合的最新日期。

您没有提到如果一组中除了'A'以外还有其他2种状态(例如'I'和'E'或NULL)会发生什么情况。在这种情况下,可能需要进行一些微调才能获得LAST_VALUE的正确值。

注意:我将c_numberc_date用于列名,因为日期和数字是保留关键字,不应该用于列。

Demo

答案 1 :(得分:0)

也许有点过时,但这应该可以工作(虽然我没有尝试过):

SELECT   `number`,
         `status`,
         MAX(`date`) AS `date`
FROM     t1
WHERE    `status` = 'A'
GROUP BY `number`,
         `status`
UNION ALL
SELECT   `number`,
         `status`,
         MAX(`date`) AS `date`
FROM     t1 t1i
WHERE    `status` = 'I'
  AND    NOT EXISTS (SELECT * from t1 t1a WHERE t1i.`number` = t1a.`number` AND t1a.`status` = 'A')
GROUP BY `number`,
         `status`;

这将为每个数字返回一行。
您的示例显示重复的行。我不确定那是否就是您想要的。