Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/postgresql/10.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
PostgreSQL分配随机、非重复的值_Sql_Postgresql_Join_Count_Window Functions - Fatal编程技术网

PostgreSQL分配随机、非重复的值

PostgreSQL分配随机、非重复的值,sql,postgresql,join,count,window-functions,Sql,Postgresql,Join,Count,Window Functions,我有一张学生表,如下所示: firstname | id ----------------+---- Student1 | 1 Student2 | 2 Student3 | 3 Student4 | 4 Student5 | 5 Student6 | 6 Student7 | 7 Student8 | 8 Student9 | 9 t

我有一张学生表,如下所示:

   firstname    | id 
----------------+----
 Student1       |  1
 Student2       |  2
 Student3       |  3
 Student4       |  4
 Student5       |  5
 Student6       |  6
 Student7       |  7
 Student8       |  8
 Student9       |  9
 topic   | n_tasks
---------+----
       1 | 11
       2 |  3
       3 |  6
       4 |  9
       5 | 12
       6 | 13
       7 | 10
       8 | 25
       9 | 10
      10 | 10
      11 | 22
      12 | 20
      14 | 18
      15 | 18
      16 |  7
table topic1

   firstname    | task 
----------------+----
 Student1       |  1
 Student8       |  2
 Student4       |  3
 Student3       |  4
 Student7       |  5
 Student9       |  6
 Student6       |  7
 Student7       |  8
 Student8       |  9
 Student1       |  10
 Student2       |  11

table topic2

   firstname    | task 
----------------+----
 Student1       |  1
 Student2       |  2
 Student3       |  3
 Student4       |  1
 Student5       |  3
 Student6       |  2
 Student7       |  2
 Student8       |  3
 Student9       |  1
以及包含每个主题要执行的任务数的表,如下所示:

   firstname    | id 
----------------+----
 Student1       |  1
 Student2       |  2
 Student3       |  3
 Student4       |  4
 Student5       |  5
 Student6       |  6
 Student7       |  7
 Student8       |  8
 Student9       |  9
 topic   | n_tasks
---------+----
       1 | 11
       2 |  3
       3 |  6
       4 |  9
       5 | 12
       6 | 13
       7 | 10
       8 | 25
       9 | 10
      10 | 10
      11 | 22
      12 | 20
      14 | 18
      15 | 18
      16 |  7
table topic1

   firstname    | task 
----------------+----
 Student1       |  1
 Student8       |  2
 Student4       |  3
 Student3       |  4
 Student7       |  5
 Student9       |  6
 Student6       |  7
 Student7       |  8
 Student8       |  9
 Student1       |  10
 Student2       |  11

table topic2

   firstname    | task 
----------------+----
 Student1       |  1
 Student2       |  2
 Student3       |  3
 Student4       |  1
 Student5       |  3
 Student6       |  2
 Student7       |  2
 Student8       |  3
 Student9       |  1
我想根据以下规则随机分配任务给学生:

  • 当任务数量与学生完全相同时,每个 学生应随机分配一个任务编号
  • 当任务多于学生时,学生名单应 重复一遍
  • 当任务少于学生时,任务列表应 重复一遍
  • 如果学生或任务需要重复,则应随机选择
输出可以存储在单独的表中,每个任务对应一个表。它看起来是这样的:

   firstname    | id 
----------------+----
 Student1       |  1
 Student2       |  2
 Student3       |  3
 Student4       |  4
 Student5       |  5
 Student6       |  6
 Student7       |  7
 Student8       |  8
 Student9       |  9
 topic   | n_tasks
---------+----
       1 | 11
       2 |  3
       3 |  6
       4 |  9
       5 | 12
       6 | 13
       7 | 10
       8 | 25
       9 | 10
      10 | 10
      11 | 22
      12 | 20
      14 | 18
      15 | 18
      16 |  7
table topic1

   firstname    | task 
----------------+----
 Student1       |  1
 Student8       |  2
 Student4       |  3
 Student3       |  4
 Student7       |  5
 Student9       |  6
 Student6       |  7
 Student7       |  8
 Student8       |  9
 Student1       |  10
 Student2       |  11

table topic2

   firstname    | task 
----------------+----
 Student1       |  1
 Student2       |  2
 Student3       |  3
 Student4       |  1
 Student5       |  3
 Student6       |  2
 Student7       |  2
 Student8       |  3
 Student9       |  1
在需要重复任务或学生的情况下,理想情况下,在所有其他学生或任务完成之前,学生或任务都不会重复


经过深思熟虑,我认为这个问题可能不适合PostgreSQL,最好用另一种编程语言来解决,但谢谢你的建议

您可以根据需要尝试此功能:

create or replace function fun(topic_id int) returns bool as
$$
declare
st_count int;
topic_count int;
begin
select count(*) into st_count from student;
select n_tasks into topic_count from topic where topicid=topic_id;

if st_count=topic_count and st_count>0 and topic_count>0 then
execute format('create table %I (first_name varchar, task int)','topic'||topic_id);
execute format('insert into %I select name,row_number() over (order by random()) rn from student','topic'||topic_id);
return true;
end if;


if st_count>topic_count and st_count>0 and topic_count>0 then
execute format('create table %I (first_name varchar, task int)','topic'||topic_id);
execute format('insert into %I 
with cte as (select generate_series(1,%s) rn), 
cte1 as (
select row_number() over (order by random()) rn, 
name from student t1) select t1.name, coalesce(t2.rn,round(random()* %s)) 
from cte1 t1 left join cte t2 on t1.rn=t2.rn',
'topic'||topic_id,topic_count,topic_count);

return true;
end if;

if st_count<topic_count and st_count>0 and topic_count>0 then
execute format('create table %I (first_name varchar, task int)','topic'||topic_id);
execute format('insert into %I with cte as (select generate_series(1,%s) rn),
cte1 as (select row_number() over (order by random()) rn, name from student t1),
cte2 as (select coalesce(t2.rn, round(random()* %s)) rn_,t1.rn from cte t1 
left join cte1 t2 on t1.rn=t2.rn) 
select t1.name,t2.rn from cte2 t2 inner join cte1 t1 on t1.rn=t2.rn_',
'topic'||topic_id,topic_count,st_count);

return true;
end if;


return false;
end;

$$
language plpgsql
这将生成具有给定条件的所有表


这是一个有趣的问题

首先,可以使用
generate_series()
创建任务行。然后,你可以随机列举学生

最后,您可以在连接条件中使用算术来考虑每一端的“缺失”行:其思想是将任务数量与学生数量进行比较,然后使用模来偏移最大组的值,并适当地分布其他不匹配的行

select s.firstname, t.task
from (
    select 
        s.*, 
        row_number() over(order by random()) rn,
        count(*) over() cnt
    from students s
) s
inner join (
    select t.*, x.task
    from topic t
    cross join lateral generate_series(1, n_tasks) as x(task)
) t 
    on (s.cnt     <= t.n_tasks  and s.rn   = t.task % s.cnt     + 1)
    or (t.n_tasks <  s.cnt      and t.task = s.rn   % t.n_tasks + 1)
where t.topic = 1
order by t.topic, t.task
专题2:

firstname | task :-------- | ---: Student9 | 1 Student3 | 1 Student7 | 1 Student1 | 2 Student6 | 2 Student8 | 2 Student4 | 3 Student2 | 3 Student5 | 3 名字|任务 :-------- | ---: 学生9 | 1 学生3 | 1 学生7 | 1 学生1 | 2 学生6 | 2 学生8 | 2 学生4 | 3 学生2 | 3 学生5 | 3
不,上述场景并不不适合PostgreSQL。尝试下面的解决方案。