当子查询返回多于1行时如何更新记录

时间:2019-06-13 10:28:12

标签: mysql sql

例如,我需要自动/随机分配一个“新”领导者来领导学生(从每种类型中仅选择1名学生),并且每天假设领导者表中共有10个领导者。

但是通过使用以下查询我得到的结果是错误的,它将在第一时间将所有学生更新为相同的领导者ID。

UPDATE students 
   SET student_status = 'assigned'
     , leader_id = 'abc' 
 WHERE student_id IN 
         ( SELECT student_id 
             FROM  
                ( SELECT * 
                    FROM students
                ) s 
            WHERE student_status = 'New'  
            GROUP
               BY type_id)

我的预期结果类似于以下查询,但是我不想运行其他逻辑来生成随机化的student_id:

UPDATE students
SET student_status='assigned', leader_id='abc' 
WHERE student_id IN ('T0123','S0222','T7777','S8888')


student_id | type_id | leader_id | student_status
-----------+---------+-----------+---------------
T0121      | Type 1  |    xyz    | assigned
T0122      | Type 1  |           | new
T0123      | Type 1  |           | new
S0221      | Type 2  |           | new
S0222      | Type 2  |           | new
S0223      | Type 2  |    xyz    | assigned
T7777      | Type 3  |           | new
T7779      | Type 3  |    xyz    | assigned
S8888      | Type 4  |    xyz    | assigned
S8887      | Type 4  |           | new
S8886      | Type 4  |           | new

3 个答案:

答案 0 :(得分:0)

使用RAND()获取介于1和最大Leader_id之间的随机leader_id,并使用ROW_NUMBER和OVER获取子类型的子查询,以更新每种类型的

UPDATE students s
JOIN (SELECT type_id, student_id, ROW_NUMBER() OVER (PARTITION BY type_id ORDER BY RAND()) rnum
      FROM students 
      WHERE status = 'new') r ON r.type_id = s.type_id AND
                                 r.student_id = s.student_id AND 
                                 rnum = 1
SET leader_id = (SELECT CEIL(RAND() * MAX(leader_id)) FROM leaders),
    status = 'assigned'
WHERE status = 'new'

答案 1 :(得分:-1)

对于MySQL:

UPDATE students 
SET student_status='assigned', leader_id='abc' 
WHERE student_id IN (
    SELECT student_id FROM  (
         SELECT * FROM students)  AS s 
    WHERE student_status ='New'  GROUP BY type_id ORDER BY RAND()
    )

答案 2 :(得分:-1)

这应该有效。这将每次从每种类型中选择一名新学生,并将相应地更新状态和领导者ID。

SELECT title, MIN(date_key_no) AS intro_date FROM table HAVING MIN(date_key_no)>= TO_NUMBER(TO_CHAR(SysDate, 'YYYYMMDD')) - 7
相关问题