Oracle查询获取数据的子选择

时间:2015-06-25 19:21:39

标签: oracle

我有一个有趣的问题,我知道我可以在代码中解决,但我认为必须有一个使用本机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子句中使用子查询,但我不知道该怎么做。

希望这是有道理的,有人可以帮我解决这个问题吗?

提前谢谢!!

2 个答案:

答案 0 :(得分:1)

SQL Fiddle

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这可能是建议的延迟或线索的替代方案,问题是你不知道在这种情况下你想要提前多远。