Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/sql/77.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Sql 任意分布的排序结果_Sql_Postgresql - Fatal编程技术网

Sql 任意分布的排序结果

Sql 任意分布的排序结果,sql,postgresql,Sql,Postgresql,我的数据库中有几千个作业,它们的列的值为“active”或“inactive”。大约5%的工作是“不活跃的”。每天都会增加工作岗位(以百为单位)。当现有作业标记为“非活动”时,我们将保持准确率(如果“非活动”作业太多,则删除) 我需要对所有作业进行排序,使“非活动”作业均匀分布。最理想的情况是,每20个“活动”作业中就有一个是“非活动”作业(结果按20分页) 我怎样才能做到这一点?数据库是Postgresql drop sequence rownum1 ; create temp sequenc

我的数据库中有几千个作业,它们的列的值为“active”或“inactive”。大约5%的工作是“不活跃的”。每天都会增加工作岗位(以百为单位)。当现有作业标记为“非活动”时,我们将保持准确率(如果“非活动”作业太多,则删除)

我需要对所有作业进行排序,使“非活动”作业均匀分布。最理想的情况是,每20个“活动”作业中就有一个是“非活动”作业(结果按20分页)

我怎样才能做到这一点?数据库是Postgresql

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序列

我同意kurast的一般方法,但有两点可能会有所帮助:

  • 我认为您需要使用nextval函数从序列中获取下一个值,如
  • x

  • 我建议在这样的查询中使用UNION ALL,因为您确信子选择返回的表不会包含第一行,因此不需要普通UNION(它有效地对组合数据执行DISTINCT),并且可能运行缓慢
  • 我认为上面的查询将在20个作业的每一页上为您提供一个非活动作业,定位在最后,但您必须使用它来确保

    请注意,在Oracle中,您可以使用ROWNUM,而不必处理序列。(提示,提示,PostgreSQL团队?)


    分享和享受。

    我会为此尝试一个用户定义的功能

    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;
    

    你应该测试所有答案,并标出一个答案
    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;
    
    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;