目标: 对于每个“ IDCONT”,我都需要获取“ DAY_ID”,其中我对“ STATE_ID”具有最后的更改/更新。
示例:
with reftable as (
select 1 as PROCESSID, 'A' as IDCONT, 'X' as STATEID, '10' AS DAY_ID union all
select 2 as PROCESSID, 'A' as IDCONT, 'X' as STATEID, '11' AS DAY_ID union all
select 3 as PROCESSID, 'A' as IDCONT, 'Y' as STATEID, '12' AS DAY_ID union all
select 4 as PROCESSID, 'A' as IDCONT, 'Y' as STATEID, '13' AS DAY_ID union all
select 1 as PROCESSID, 'B' as IDCONT, 'N' as STATEID, '14' AS DAY_ID union all
select 2 as PROCESSID, 'B' as IDCONT, 'N' as STATEID, '15' AS DAY_ID union all
select 3 as PROCESSID, 'B' as IDCONT, 'M' as STATEID, '16' AS DAY_ID union all
select 1 as PROCESSID, 'C' as IDCONT, 'X' as STATEID, '11' AS DAY_ID union all
select 2 as PROCESSID, 'C' as IDCONT, 'X' as STATEID, '18' AS DAY_ID union all
) ...
预期结果:
PROCESSID IDCONT STATID DAYID
3 A Y 12
2 B N 15
1 C X 11
我解决了这个问题:
...
SELECT IDCONT, STATEID, MIN(DAY_ID)
FROM REFTABLE
WHERE (IDCONT, STATEID) IN (
SELECT IDCONT, FIRST_VALUE(STATEID) OVER PARTITION BY IDCONT ORDER BY PROCESSID DESC) AS STATEID
FROM REFTABLE
)
但是我想做同样的事情而无需第二次调用表。
谢谢!
答案 0 :(得分:1)
如果您不需要返回IDCONT
不变的STATEID
(这将是一个C
),那会更简单。 REFTABLE
一趟可能看起来像这样;看看它是否对 reality 有帮助。
SQL> with reftable as (
2 select 1 as PROCESSID, 'A' as IDCONT, 'X' as STATEID, '10' AS DAY_ID from dual union all
3 select 2 as PROCESSID, 'A' as IDCONT, 'X' as STATEID, '11' AS DAY_ID from dual union all
4 select 3 as PROCESSID, 'A' as IDCONT, 'Y' as STATEID, '12' AS DAY_ID from dual union all
5 select 4 as PROCESSID, 'A' as IDCONT, 'Y' as STATEID, '13' AS DAY_ID from dual union all
6 --
7 select 1 as PROCESSID, 'B' as IDCONT, 'N' as STATEID, '14' AS DAY_ID from dual union all
8 select 2 as PROCESSID, 'B' as IDCONT, 'N' as STATEID, '15' AS DAY_ID from dual union all
9 select 3 as PROCESSID, 'B' as IDCONT, 'M' as STATEID, '16' AS DAY_ID from dual union all
10 --
11 select 1 as PROCESSID, 'C' as IDCONT, 'X' as STATEID, '11' AS DAY_ID from dual union all
12 select 2 as PROCESSID, 'C' as IDCONT, 'X' as STATEID, '18' AS DAY_ID from dual
13 ),
14 inter as
15 (select processid, idcont, stateid, day_id,
16 case when nvl(lag(stateid) over
17 (partition by idcont order by processid ), '?') <> stateid then
18 row_number() over (partition by idcont order by processid )
19 end grp
20 from reftable
21 )
22 select processid, idcont, stateid, day_id
23 from inter i
24 where grp = (select max(i1.grp)
25 from inter i1
26 where i1.idcont = i.idcont)
27 order by idcont, processid;
PROCESSID IDCONT STATEID DAY_ID
---------- ---------- ---------- ----------
3 A Y 12
3 B M 16
1 C X 11
SQL>
答案 1 :(得分:1)
这是一种方法:
cb
但是,这不能处理状态变回先前状态的情况。如有必要,可以添加该逻辑。
答案 2 :(得分:0)
使用“ FIRST_VALUE”确实可以进行更改,但是您可以依靠表中的单个更改吗?其他更改不会使此操作无效并导致错误的数据吗?
我改用了LAG函数,但是它没有返回IDCONT C,因为它没有变化。
使用CTE来获取数据,然后使用查询进行过滤可能会更快(因为您不能在where子句中放置LAG或FIRST_VALUE)。这样可以防止再次访问数据库。
CREATE TABLE REFTABLE
([PROCESSID] int, [IDCONT] varchar(1), [STATEID] varchar(1), [DAY_ID] int)
;
INSERT INTO REFTABLE
([PROCESSID], [IDCONT], [STATEID], [DAY_ID])
VALUES
(1, 'A', 'X', 10),
(2, 'A', 'X', 11),
(3, 'A', 'Y', 12),
(4, 'A', 'Y', 13),
(1, 'B', 'N', 14),
(2, 'B', 'N', 15),
(3, 'B', 'M', 16),
(1, 'C', 'X', 11),
(2, 'C', 'X', 18)
;
with chgfound as (SELECT TOP 100 PERCENT PROCESSID, IDCONT, STATEID, DAY_ID, LAG(STATEID) OVER(PARTITION BY IDCONT ORDER BY IDCONT, PROCESSID) as LastState
from REFTABLE
order by IDCONT, PROCESSID
)
select * from chgfound where STATEID !=LastState
http://www.sqlfiddle.com/#!18/086134
也只是注意到您具有Oracle标签。我在SQL Server中做到了这一点,但它必须与之接近。