SQL - 对动态表使用案例语句(未知行数)
Posted
技术标签:
【中文标题】SQL - 对动态表使用案例语句(未知行数)【英文标题】:SQL - Using Case Statements with Dynamic tables (unknown row count) 【发布时间】:2018-03-21 00:16:12 【问题描述】:我在尝试创建存储过程时遇到了一点问题。我有 2 张桌子,eTasks
和 eStaff
。以下是每个表的列:
电子任务
TaskID | StaffID | Title | CreateDate
电子员工
StaffID | Name
目前,就数据而言,所有任务都分配给 StaffID '1'。 eTasks
和 eStaff
表都使用新任务和员工进行更新,或者它们被删除,这些表每天都不会有完全相同的行。有时,eTask
表中有 1000 行,接下来可能只有 400 行。有时,eStaff
表中有 3 名员工,接下来可能有 12 人。
当我运行我的存储过程时,我想做的是在当前StaffID
s 之间平均分配任务。
到目前为止,这就是我所拥有的:
CREATE PROCEDURE UpdatingeTasksTable
AS
DECLARE t_rowCount INTEGER
DECLARE s_staffIDCount INTEGER
SET t_rowCount = SELECT COUNT(*) FROM eTasks
SET s_staffIDCount = SELECT DISTINCT StaffID FROM eStaff
UPDATE eTasks
SET StaffID = CASE
WHEN TaskID % t_rowCount = 1 THEN 1
WHEN TaskID % t_rowCount = 2 THEN 4
WHEN TaskID % t_rowCount = 3 THEN 3
WHEN TaskID % t_rowCount = 4 THEN 2
END
FROM eTasks b
WHERE TaskID = b.TaskID;
我知道,我的查询目前如何,它只会将任务分配给 4 个人。有没有办法让 CASE 语句动态化,这样就不仅仅是一组静态数字?
【问题讨论】:
【参考方案1】:这在 mysql 中有点困难。您可以通过添加行号列来编写查询:
select et.*, s.staffId
from (select count(*) as cnt
from staff
) ss cross join
(select et.*, (@rne := @rne + 1) as rn
from etasks et cross join
(select @rne := 0) params
) et join
(select s.*, (@rns := @rns + 1) as rn
from staff s cross join
(select @rns := 0) params
) s
on s.rn = mod(et.rn, ss.cnt) + 1;
然后您可以使用join
将其放入update
:
update etask et join
(select et.*, s.staffId
from (select count(*) as cnt
from staff
) ss cross join
(select et.*, (@rne := @rne + 1) as rn
from etasks et cross join
(select @rne := 0) params
) et join
(select s.*, (@rns := @rns + 1) as rn
from staff s cross join
(select @rns := 0) params
) s
on s.rn = mod(et.rn, ss.cnt) + 1
) ets
on et.taskid = ets.taskid
set et.staffid = ets.staffid;
【讨论】:
【参考方案2】:我得到了这个测试。我没有使用存储过程,我只是在 MySQL 会话中使用用户定义的变量。但同样的想法也适用于本地存储过程变量。
mysql> select count(*) into @staffcount from estaff; -- in my test this is 4
mysql> set @staffid = 0;
mysql> update etasks set staffid = (@staffid := (@staffid+1)%@staffcount)+1;
mysql> select * from etasks;
+--------+---------+-------+------------+
| taskid | staffid | title | createdate |
+--------+---------+-------+------------+
| 1 | 2 | NULL | NULL |
| 2 | 3 | NULL | NULL |
| 3 | 4 | NULL | NULL |
| 4 | 1 | NULL | NULL |
| 5 | 2 | NULL | NULL |
| 6 | 3 | NULL | NULL |
| 7 | 4 | NULL | NULL |
| 8 | 1 | NULL | NULL |
| 9 | 2 | NULL | NULL |
| 10 | 3 | NULL | NULL |
| 11 | 4 | NULL | NULL |
| 12 | 1 | NULL | NULL |
| 13 | 2 | NULL | NULL |
| 14 | 3 | NULL | NULL |
| 15 | 4 | NULL | NULL |
| 16 | 1 | NULL | NULL |
| 17 | 2 | NULL | NULL |
| 18 | 3 | NULL | NULL |
+--------+---------+-------+------------+
这确实假设您的 staffid 值已知从 1 到 estaff 中的行数。如果要将值 1 到 4 映射到 estaff 中的相应行,并分配 staffid,这里有一个解决方案:
mysql> update etasks as t,
(select staffid, @rownum:=@rownum+1 AS rownum
from (select @rownum:=0) AS _init cross join estaff) as s
set t.staffid = s.staffid
where s.rownum = (@staffid := (@staffid+1)%@staffcount)+1;
【讨论】:
以上是关于SQL - 对动态表使用案例语句(未知行数)的主要内容,如果未能解决你的问题,请参考以下文章