我的数据库中有很少的thousends作业,其列的值为“active”或“inactive”。大约5%的工作是“不活跃的”。每天添加工作(以数量为单位)。当现有作业被标记为“不活动”时,我们将比率保持准确(如果有太多的作业,则删除“非活动”作业)。
我需要以“非活动”作业均匀分布的方式对所有作业进行排序。最好每20个“活动”作业中就有一个应该是“非活动”作业(结果分为20个)。
我怎样才能实现这一目标?数据库是Postgresql。
答案 0 :(得分:1)
drop sequence rownum1 ;
create temp sequence rownum1;
drop sequence rownum2 ;
create temp sequence rownum2;
select * from(
select job_name, rownum1*20 as myorder from jobs where job_status =0
union
select job_name, rownum2 as myorder from jobs where job_status =1
)
order by myorder desc
如果查询对活动作业的比例为1到20不活动,则此查询将使它们均匀分布。如果您具有超过此最佳比率,则查询顶部将包含大量非活动作业。 每次运行此查询时,您都需要删除并重新创建rownums序列
答案 1 :(得分:0)
我同意kurast的一般方法,但有几点可能会有所帮助:
X
SELECT * FROM
(SELECT *, nextval('rownum1') AS SORT_ORDER
FROM JOBS
WHERE JOB_STATUS = 'active'
UNION ALL
SELECT *, nextval('rownum2') * 19 AS SORT_ORDER
FROM JOBS
WHERE JOB_STATUS = 'inactive')
ORDER BY SORT_ORDER, JOB_STATUS;
我认为上述查询会在20个作业的每个页面上为您提供一个非活动作业,最后定位,但您必须使用它才能确定。
请注意,在Oracle中,您可以使用ROWNUM而不必乱用序列。 (提示,提示,PostgreSQL团队?)
分享并享受。
答案 2 :(得分:0)
我会为此尝试一个用户定义的函数。
create table jobs (
id serial primary key,
job_status smallint not null default 1,
job_name text default 'FIXME',
inserted timestamptz default now()
);
insert into jobs ( job_status,inserted )
select case when random()<=0.05 then 0 else 1 end, localtimestamp
from generate_series(1,1000) x(x);
create or replace function get_jobs(p_limit int,p_offset int)
returns setof jobs as $$
declare
v_limit1 integer;
v_offset2 integer;
rec record;
begin
v_limit1 := p_limit - 1;
v_offset2 := p_offset / 20;
for rec in select * from jobs where job_status=1
order by inserted desc limit v_limit1 offset p_offset
loop
return next rec;
end loop;
return query select * from jobs where job_status=0 offset v_offset2 limit 1;
return;
end;
$$ language plpgsql;
这将在页面的最后位置列出一个“非活动”作业。代码可能需要一些抛光,但你明白了。
希望这有帮助。
PS。 @kurast:你的解决方案在PostgreSQL 8.4.1中不起作用。它甚至在语法上都不正确。在纠正语法之后,它也不起作用。见下文。
select * from(
select *, nextval('rownum1')*20 as myorder from jobs where job_status =0
union
select *, nextval('rownum2') as myorder from jobs where job_status =1
) subq
order by myorder desc;