如何 Dense_Rank() 重复的值集
How to Dense_Rank() Sets of Values that Repeat
我有一个 table T
如下所示:
T Table
EMPLID CODE DT
101 PPP 01-JAN-15
101 PPP 02-JAN-15
101 PPP 03-JAN-15
101 OOO 04-JAN-15
101 OOO 05-JAN-15
101 PPP 06-JAN-15
101 PPP 07-JAN-15
101 PPP 08-JAN-15
101 PPP 09-JAN-15
我想要的是如下结果:
EMPLID CODE RNK DT
101 PPP 1 01-JAN-15
101 PPP 1 02-JAN-15
101 PPP 1 03-JAN-15
101 OOO 2 04-JAN-15
101 OOO 2 05-JAN-15
101 PPP 3 06-JAN-15
101 PPP 3 07-JAN-15
101 PPP 3 08-JAN-15
101 PPP 3 09-JAN-15
但我似乎只得到如下结果:
SELECT EMPLID, CODE, DENSE_RANK() OVER(ORDER BY CODE) AS RNK, DT
FROM T;
EMPLID CODE RNK DT
101 OOO 1 05-JAN-15
101 OOO 1 04-JAN-15
101 PPP 2 03-JAN-15
101 PPP 2 08-JAN-15
101 PPP 2 09-JAN-15
101 PPP 2 06-JAN-15
101 PPP 2 07-JAN-15
101 PPP 2 02-JAN-15
101 PPP 2 01-JAN-15
由于 PPP
值在 OOO
值之后重复,但在以后的日期,我不确定如何 group/order 它以便我得到 RNK
将第二组 PPP
值视为第三组的字段。
下面是 table 的代码,可以让这更容易一些:
WITH
T AS(
SELECT '101' AS EMPLID, 'PPP' AS CODE, '01-JAN-15' AS DT FROM DUAL
UNION ALL
SELECT '101', 'PPP', '02-JAN-15' FROM DUAL
UNION ALL
SELECT '101', 'PPP', '03-JAN-15' FROM DUAL
UNION ALL
SELECT '101', 'OOO', '04-JAN-15' FROM DUAL
UNION ALL
SELECT '101', 'OOO', '05-JAN-15' FROM DUAL
UNION ALL
SELECT '101', 'PPP', '06-JAN-15' FROM DUAL
UNION ALL
SELECT '101', 'PPP', '07-JAN-15' FROM DUAL
UNION ALL
SELECT '101', 'PPP', '08-JAN-15' FROM DUAL
UNION ALL
SELECT '101', 'PPP', '09-JAN-15' FROM DUAL
)
SELECT *
FROM T;
我认为您需要两遍:首先找到代码更改的所有行,然后在此基础上构建一个组。
select emplid, code, sum(change) over (order by dt) as rnk, dt
from
(
select
emplid,
code,
case when lag(code) over (order by dt) = code then 0 else 1 end as change,
dt
from t
order by dt
);
如果我没理解错的话,您想按 dt 对结果进行排序。您可以为每个更改的行设置标志,然后将标志加到该行,这将得到与 DENSE_RANK:
相同的结果
SELECT
sel2.emplid,
sel2.code,
SUM (sel2.flg) OVER (ORDER BY sel2.dt ROWS BETWEEN UNBOUNDED PRECEDING AND 0 PRECEDING) rnk,
sel2.dt
FROM
( SELECT
sel1.emplid,
sel1.code,
CASE WHEN sel1.code = sel1.code_lag THEN 0 ELSE 1 END flg,
sel1.dt
FROM
( SELECT emplid, code, dt, LAG(code,1,'XXX') OVER (ORDER BY dt) code_lag
FROM T
) sel1
) sel2
ORDER BY dt;
您唯一需要注意的是,无论天气如何,最后的结果都将被视为单独的排名。
也可以递归求解:
with s (u, s, a, n) as (
select emplid, code, 1, dt from t where dt = date '2015-01-01'
union all select emplid, code, a+decode(code, s, 0, 1), dt from t join s on dt=n+1 )
select * from s
我有一个 table T
如下所示:
T Table
EMPLID CODE DT
101 PPP 01-JAN-15
101 PPP 02-JAN-15
101 PPP 03-JAN-15
101 OOO 04-JAN-15
101 OOO 05-JAN-15
101 PPP 06-JAN-15
101 PPP 07-JAN-15
101 PPP 08-JAN-15
101 PPP 09-JAN-15
我想要的是如下结果:
EMPLID CODE RNK DT
101 PPP 1 01-JAN-15
101 PPP 1 02-JAN-15
101 PPP 1 03-JAN-15
101 OOO 2 04-JAN-15
101 OOO 2 05-JAN-15
101 PPP 3 06-JAN-15
101 PPP 3 07-JAN-15
101 PPP 3 08-JAN-15
101 PPP 3 09-JAN-15
但我似乎只得到如下结果:
SELECT EMPLID, CODE, DENSE_RANK() OVER(ORDER BY CODE) AS RNK, DT
FROM T;
EMPLID CODE RNK DT
101 OOO 1 05-JAN-15
101 OOO 1 04-JAN-15
101 PPP 2 03-JAN-15
101 PPP 2 08-JAN-15
101 PPP 2 09-JAN-15
101 PPP 2 06-JAN-15
101 PPP 2 07-JAN-15
101 PPP 2 02-JAN-15
101 PPP 2 01-JAN-15
由于 PPP
值在 OOO
值之后重复,但在以后的日期,我不确定如何 group/order 它以便我得到 RNK
将第二组 PPP
值视为第三组的字段。
下面是 table 的代码,可以让这更容易一些:
WITH
T AS(
SELECT '101' AS EMPLID, 'PPP' AS CODE, '01-JAN-15' AS DT FROM DUAL
UNION ALL
SELECT '101', 'PPP', '02-JAN-15' FROM DUAL
UNION ALL
SELECT '101', 'PPP', '03-JAN-15' FROM DUAL
UNION ALL
SELECT '101', 'OOO', '04-JAN-15' FROM DUAL
UNION ALL
SELECT '101', 'OOO', '05-JAN-15' FROM DUAL
UNION ALL
SELECT '101', 'PPP', '06-JAN-15' FROM DUAL
UNION ALL
SELECT '101', 'PPP', '07-JAN-15' FROM DUAL
UNION ALL
SELECT '101', 'PPP', '08-JAN-15' FROM DUAL
UNION ALL
SELECT '101', 'PPP', '09-JAN-15' FROM DUAL
)
SELECT *
FROM T;
我认为您需要两遍:首先找到代码更改的所有行,然后在此基础上构建一个组。
select emplid, code, sum(change) over (order by dt) as rnk, dt
from
(
select
emplid,
code,
case when lag(code) over (order by dt) = code then 0 else 1 end as change,
dt
from t
order by dt
);
如果我没理解错的话,您想按 dt 对结果进行排序。您可以为每个更改的行设置标志,然后将标志加到该行,这将得到与 DENSE_RANK:
相同的结果SELECT
sel2.emplid,
sel2.code,
SUM (sel2.flg) OVER (ORDER BY sel2.dt ROWS BETWEEN UNBOUNDED PRECEDING AND 0 PRECEDING) rnk,
sel2.dt
FROM
( SELECT
sel1.emplid,
sel1.code,
CASE WHEN sel1.code = sel1.code_lag THEN 0 ELSE 1 END flg,
sel1.dt
FROM
( SELECT emplid, code, dt, LAG(code,1,'XXX') OVER (ORDER BY dt) code_lag
FROM T
) sel1
) sel2
ORDER BY dt;
您唯一需要注意的是,无论天气如何,最后的结果都将被视为单独的排名。
也可以递归求解:
with s (u, s, a, n) as (
select emplid, code, 1, dt from t where dt = date '2015-01-01'
union all select emplid, code, a+decode(code, s, 0, 1), dt from t join s on dt=n+1 )
select * from s