需求是这样的:一个contract_number可能有多个period_id
(1)如果一个contract_number值对应一个period_id,那么取row_number = 1的那一条
(1)如果一个contract_number值对应多个period_id,那么从dense_rank()=2中取一条(因为dense_rank()=2可能存在多条);以下是我写的代码,大家帮忙优化下!
当然大家若有其他方法实现,那就再好不过了!select contract_number, period_id
from(select contract_number,
period_id,
rn,
cnt,
row_number() over(partition by dr order by dr) rnb
from(select contract_number,
period_id,
dense_rank() over(partition by contract_number order by period_id desc) dr,
row_number() over(partition by contract_number order by period_id desc) rn,
count(*) over(partition by contract_number order by period_id desc) cnt
from ods_asms_order_detail
where period_id >= 20100101
and period_id < 20110101
)
)
where rn = (case when cnt = 1 then 1 else 0 end) or rnb = (case when cnt >=2 then 2 else 0 end);
(1)如果一个contract_number值对应一个period_id,那么取row_number = 1的那一条
(1)如果一个contract_number值对应多个period_id,那么从dense_rank()=2中取一条(因为dense_rank()=2可能存在多条);以下是我写的代码,大家帮忙优化下!
当然大家若有其他方法实现,那就再好不过了!select contract_number, period_id
from(select contract_number,
period_id,
rn,
cnt,
row_number() over(partition by dr order by dr) rnb
from(select contract_number,
period_id,
dense_rank() over(partition by contract_number order by period_id desc) dr,
row_number() over(partition by contract_number order by period_id desc) rn,
count(*) over(partition by contract_number order by period_id desc) cnt
from ods_asms_order_detail
where period_id >= 20100101
and period_id < 20110101
)
)
where rn = (case when cnt = 1 then 1 else 0 end) or rnb = (case when cnt >=2 then 2 else 0 end);
--这样可以吗?没测试哈
select contract_number, period_id from (
select contract_number,
period_id,
dense_rank() over(partition by contract_number order by period_id desc) dr,
row_number() over(partition by contract_number order by period_id desc) rn,
count(*) over(partition by contract_number order by period_id desc) cnt
from ods_asms_order_detail
where period_id >= 20100101 and period_id < 20110101
)
where (cnt=1 and rn=1) or (cnt!=1 and dr=2 and rn=2)
不对,你可以考虑rn永远>=dr 所以说:当dr =2时, rn极有可能不等于2.
故:(cnt!=1 and dr=2 and rn=2)是错误的!
那么对应多个period_id时候,只取dr=2中的一个,那么rn就对应2,3,4啊
不知道我说的对不对,还请你多指示
where rn = (case when cnt = 1 then 1 else 0 end) or rnb = (case when cnt >=2 then 2 else 0 end);
--可以改为
---cnt=1 rn始终是 1 cnt>=2 则含有 rnb=1,2,3...
rn=1 or rnb=2
select contract_number, period_id,
count(*) over (partition by contract_number) cnt,
dense_rank() over (partition by contract_number order by period_id) dr
from ods_asms_order_detail
)
select contract_number,max(period_id)
from t t1
where cnt=1 or dr=2
group by contract_number
/
select contract_number,
period_id,
dense_rank() over(partition by contract_number order by period_id desc) dr,
row_number() over(partition by contract_number order by period_id desc) rn,
count(*) over(partition by contract_number order by 1) cnt
from ods_asms_order_detail
where period_id >= 20100101 and period_id < 20110101
)
where (cnt=1 and rn=1) or (cnt>1 and dr=2 or cnr - rn + dr = 1);
--明白了,不过你7楼的好像也不行。但是看了xman_78tom的好像可以
--嗯这个不错
select contract_number, max(period_id) from (
select contract_number,
period_id,
dense_rank() over(partition by contract_number order by period_id desc) dr,
row_number() over(partition by contract_number order by period_id desc) rn,
count(*) over(partition by contract_number order by period_id desc) cnt
from ods_asms_order_detail
where period_id >= 20100101 and period_id < 20110101
)
where cnt=1 or dr=2
group by contract_number
period_id的情况。我下面的SQL是正确的,其实和7楼完全一样!select distinct contract_number, period_id
from (select contract_number,
period_id,
dense_rank() over(partition by contract_number order by period_id desc) dr,
row_number() over(partition by contract_number order by period_id desc) rn,
count(*) over(partition by contract_number order by 1) cnt
from ods_asms_order_detail
where period_id >= 20100101
and period_id < 20110101
)
where cnt = 1
or (cnt > 1 and (dr = 2 or cnt - rn + dr = 1));
with t as (
select contract_number,
period_id,
count(*) over(partition by contract_number order by 1) cnt,
row_number() over(partition by contract_number order by period_id desc) rn,
dense_rank() over(partition by contract_number order by period_id) dr
from ods_asms_order_detail
where period_id >= 20100101
and period_id < 20110101
)
select contract_number,max(period_id)
from t t1
where cnt=1 or dr=2 or (cnt > 1 and rn = 1);