我有一个有趣的问题,我知道我可以在代码中解决,但我认为必须有一个使用本机SQL的优雅解决方案。这是我的问题...
我有一张桌子(OP),显示需要在零件上执行的所有操作(激光,抖落,打孔等) 它看起来像这样
Op# WorkCenter Job# Status
10 Laser 11222 C
15 Shake-Out 11222 C
20 Brake 11222 O
30 WashDown 11222 O
40 Paint 11222 O
10 Punch 11250 C
15 Shake-Out 11250 C
20 Brake 11250 O
30 WashDown 11250 O
40 Paint 11250 O
10 Laser 11260 C
15 Shake-Out 11260 C
20 Brake 11260 C
30 WashDown 11260 C
40 Paint 11260 C
10 Laser 11260 C
15 Shake-Out 11260 O
20 Brake 11260 O
30 WashDown 11260 O
40 Paint 11260 O
所以我想要的是从OP中选择*,显示NEXT工作中心在Shake-Out之后的状态,其中Shake-Out状态为C,下一个WC为O.
使用上述数据,我希望看到以下记录作为我的结果:
Op# WorkCenter Job# Status
20 Brake 11222 O
20 Brake 11250 O
我很确定我需要在select或from子句中使用子查询,但我不知道该怎么做。
希望这是有道理的,有人可以帮我解决这个问题吗?
提前谢谢!!
答案 0 :(得分:1)
Oracle 11g R2架构设置:
CREATE TABLE OP ( Op_number, WorkCenter, Job_number, Status ) AS
SELECT 10, 'Laser', 11222, 'C' FROM DUAL
UNION ALL SELECT 15, 'Shake-Out', 11222, 'C' FROM DUAL
UNION ALL SELECT 20, 'Brake', 11222, 'O' FROM DUAL
UNION ALL SELECT 30, 'WashDown', 11222, 'O' FROM DUAL
UNION ALL SELECT 40, 'Paint', 11222, 'O' FROM DUAL
UNION ALL SELECT 10, 'Punch', 11250, 'C' FROM DUAL
UNION ALL SELECT 15, 'Shake-Out', 11250, 'C' FROM DUAL
UNION ALL SELECT 20, 'Brake', 11250, 'O' FROM DUAL
UNION ALL SELECT 30, 'WashDown', 11250, 'O' FROM DUAL
UNION ALL SELECT 40, 'Paint', 11250, 'O' FROM DUAL
UNION ALL SELECT 10, 'Laser', 11260, 'C' FROM DUAL
UNION ALL SELECT 15, 'Shake-Out', 11260, 'C' FROM DUAL
UNION ALL SELECT 20, 'Brake', 11260, 'C' FROM DUAL
UNION ALL SELECT 30, 'WashDown', 11260, 'C' FROM DUAL
UNION ALL SELECT 40, 'Paint', 11260, 'C' FROM DUAL
UNION ALL SELECT 10, 'Laser', 11280, 'C' FROM DUAL
UNION ALL SELECT 15, 'Shake-Out', 11280, 'O' FROM DUAL
UNION ALL SELECT 20, 'Brake', 11280, 'O' FROM DUAL
UNION ALL SELECT 30, 'WashDown', 11280, 'O' FROM DUAL
UNION ALL SELECT 40, 'Paint', 11280, 'O' FROM DUAL;
查询1 :
SELECT Op_Number,
WorkCenter,
Job_Number,
Status
FROM (
SELECT o.*,
LAG( WorkCenter ) OVER ( PARTITION BY Job_Number ORDER BY Op_Number ) AS prev_workcenter,
LAG( Status ) OVER ( PARTITION BY Job_Number ORDER BY Op_Number ) AS prev_status
FROM OP o
)
WHERE prev_workcenter = 'Shake-Out'
AND prev_status = 'C'
AND status = 'O'
<强> Results 强>:
| OP_NUMBER | WORKCENTER | JOB_NUMBER | STATUS |
|-----------|------------|------------|--------|
| 20 | Brake | 11222 | O |
| 20 | Brake | 11250 | O |
答案 1 :(得分:0)
这是一个极端的查询,不幸的是,我现在没有Oracle实例/ sqlplus来对其进行测试。如果你当时没有得到答案,我将在明天通过一个完整的问题进行更新
select op#, row_number() over (partition by job_id, order by op#)
from (
select op#,workcenter,job#,status
from tab
where job_id = (select job_id
from tab
where status = 'C' and workcenter = 'Shake-Out')
and op# > (select op#
from tab
where status = 'C' and workcenter = 'Shake-Out')
order by job_id, op#) tab2
where status = 'O'
这个想法是让工作中心的任何工作都以状态C振荡并获得他们的工作号码。然后查找比这更大的操作#并使用状态为0的下一行。因此,您只需在父查询中选择1的rownum。
PS这可能是建议的延迟或线索的替代方案,问题是你不知道在这种情况下你想要提前多远。