我在名为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
请帮助我完成工作。谢谢:)
答案 0 :(得分:1)
这可以使用MIN
和LAST_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_number
和c_date
用于列名,因为日期和数字是保留关键字,不应该用于列。
答案 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`;
这将为每个数字返回一行。
您的示例显示重复的行。我不确定那是否就是您想要的。