Mysql 仅按列值更新同一组中的行
给定一个包含3列和几行的表:Mysql 仅按列值更新同一组中的行,mysql,Mysql,给定一个包含3列和几行的表: +--------+------------+--------+ | name | postalcode | toggle | +--------+------------+--------+ | john | 10100 | 0 | | joe | 10100 | 0 | | tom | 10100 | 0 | | steven | 77777 | 0 | | je
+--------+------------+--------+
| name | postalcode | toggle |
+--------+------------+--------+
| john | 10100 | 0 |
| joe | 10100 | 0 |
| tom | 10100 | 0 |
| steven | 77777 | 0 |
| jerry | 10100 | 0 |
| albert | 77777 | 0 |
| paul | 77777 | 0 |
| mary | 88888 | 0 |
| louis | 10100 | 0 |
| claire | 77777 | 0 |
+--------+------------+--------+
我想更新在N
行上使用限制将切换
值设置为1,但是在切换
列上具有相同后代码
的行不能具有不同的值
例如:
- 如果我想更新2行,只更新
[mary]
- 如果我想升级4行,
[steven,albert,paul,claire]
将被更新
- 如果我想更新5行,
[john,joe,tom,jerry,louis]
或[steven,albert,paul,mary,claire]
将被更新
考虑到我将处理N行,如何以方便/高效的方式执行此操作?恐怕您无法在单个查询中执行此操作,但您需要一个存储过程,该存储过程接受要更新的最大行数作为参数,然后执行类似的操作
var rows_left = max_rows
while(rows_left > 0){
select postal_code into cur_code, count(*) into cur_count
from yourTable
group by postal_code
having count(*) <= rows_left
limit 1
update yourTable
set toggle = 1
where postal_code = cur_code
rows_left = rows_left - cur_count
}
var rows\u left=最大行数
而(左行>0){
将邮政编码选择为当前编码,将计数(*)选择为当前计数
从你的桌子上
按邮政编码分组
拥有count(*)这是我评论中的一个快速版本
基本数据:从myTable中选择*;
+--------+------------+--------+
| name | postalCode | toggle |
+--------+------------+--------+
| john | 10100 | 0 |
| joe | 10100 | 0 |
| tom | 10100 | 0 |
| steven | 77777 | 0 |
| jerry | 10100 | 0 |
| albert | 77777 | 0 |
| paul | 77777 | 0 |
| mary | 88888 | 0 |
| louis | 10100 | 0 |
| claire | 77777 | 0 |
+--------+------------+--------+
试验程序以N为参数
如果找不到计数为N的postalCode,请使用N-1重试。
这样,N=2,更新计数=1
drop procedure if exists test;
create procedure test(in tofind int)
begin
SET @go=1, @toFind=tofind;
while(@go) do
Select @_pc:=postalCode as pc, @_count:=count(*) as cnt
from myTable
group by postalCode
having count(*) = @toFind;
If(@_count is null and @_count>1 ) then
SET @toFind = @toFind-1;
else
SET @go=0;
UPDATE myTable
SET toggle=1
WHERE postalCode=@_pc;
end if;
END WHILE ;
End;
调用N=3的过程,应更新mary
call test(3);
select * from myTable;
结果
+--------+------------+--------+
| name | postalcode | toggle |
+--------+------------+--------+
| john | 10100 | 0 |
| joe | 10100 | 0 |
| tom | 10100 | 0 |
| steven | 77777 | 0 |
| jerry | 10100 | 0 |
| albert | 77777 | 0 |
| paul | 77777 | 0 |
| mary | 88888 | 1 |
| louis | 10100 | 0 |
| claire | 77777 | 0 |
+--------+------------+--------+
重置表格以进行更多测试
UPDATE myTable SET toggle=0;
考虑到真实数据集更为复杂,我需要保证在选择将要更新的组时的随机性,我可能最终会这样做;因此为了共享:
set @N:=2;
set @i:=0;
select postalcode,sum(NBR)
from (
SELECT postalcode
, if(@i+NBR>@N,0,1) as elected
, if(@i+NBR>@N,@i,@i:=@i+NBR) as indice
, NBR
FROM ( SELECT postalcode,COUNT(DISTINCT name) AS NBR FROM myTable GROUP BY postalcode ORDER BY RAND() ) A
GROUP BY postalcode
having elected= 1
ORDER BY postalcode
) a GROUP BY postalcode
;
请提供澄清的预期结果。@ElChupacabra,问题已经在“示例”框中,如果所选组不止一个(如第3个示例中所示),则应更新哪些。如果某些行的切换值不同于其他行(在同一组中),则新的切换值应是什么为什么更新2行应该更新mary?可能是2行是最大行数。因此它可以是等于或小于N的任何值,以解决“您的帖子似乎包含未正确格式化为代码的代码。”如果您想尝试编辑,请玩得开心。谢谢,对于当前示例,您的解决方案听起来足够合理,我会接受。但是我觉得有点困惑,我想我会采取另一种方法(参见我的自我回答)。它对第三个示例有效吗?我想对于N=5,它只满足所讨论的第三个示例的第一种情况