gpt4 book ai didi

mysql - 在公共(public)数据上对逗号分隔值进行分组

转载 作者:可可西里 更新时间:2023-11-01 07:45:29 24 4
gpt4 key购买 nike

我有一个表,col1 id int,col2 为 varchar(逗号分隔值),第 3 列用于为它们分配组。表格看起来像

  col1          col2     group
..............................
1 2,3,4
2 5,6
3 1,2,5
4 7,8
5 11,3
6 22,8

这只是真实数据的样本,现在我必须以输出看起来像这样的方式为它们分配一个组号

  col1          col2       group
..............................
1 2,3,4 1
2 5,6 1
3 1,2,5 1
4 7,8 2
5 11,3 1
6 22,8 2

分配组号的逻辑是,col2 中每个类似的字符串的逗号分隔值必须与 col2 中的每个位置相同的组号,其中“2”在那里它必须是相同的组号,但复杂的是 2 ,3,4 在一起,所以如果在 col2 中的任何位置找到它们,它们的所有三个 int 值将被分配到同一组。 col2 中的主要部分是 2,3,4 和 1,2,5 都有 2,因此所有 int 1,2,3,4,5 必须分配相同的组号。尝试在 col2 上匹配存储过程但未获得所需结果

大多数 imp(我不能使用规范化,因为我无法从拥有数百万条记录的原始表中创建新表),即使规范化在我的上下文中也无济于事。


目前已经实现......我已经设置了组列自动递增,然后编写了这个程序:-

BEGIN
declare cil1_new,col2_new,group_new int;
declare done tinyint default 0;
declare group_new varchar(100);
declare cur1 cursor for select col1,col2,`group` from company ;
DECLARE CONTINUE HANDLER FOR NOT FOUND SET done=1;
open cur1;
REPEAT
fetch cur1 into col1_new,col2_new,group_new;
update company set group=group_new where
match(col2) against(concat("'",col2_new,"'"));
until done end repeat;
close cur1;
select * from company;
END

这个过程是有效的,没有句法错误,但问题是我没有完全达到预期的结果。

最佳答案

这是可能的,但我不确定这在您的大 table 上需要多长时间。我假设您被允许创建一个包含所有组的新表,并且在填充组列时有数字。

此外,这不能在实时表上运行。不可能写出来,所以这不是我设计的限制。想一想如果您添加一个值为 7 和“6,7”的新行会发生什么情况,这将桥接组 1 和组 2,并且所有工作都必须被放弃。

每次有添加到表中时,都需要重新运行此过程。如果这是 Not Acceptable ,请运行一次,然后将其替换为维护值并在需要时合并组的触发器。

这是程序。它可以从一些模块化中受益,但它确实有效。我选了 Jay Pipes split_string函数并将其包含在内。

首先是DDL和一些测试数据

CREATE TABLE `company` (
`col1` int(11) DEFAULT NULL,
`col2` varchar(100) DEFAULT NULL,
`grp` int(11) DEFAULT NULL
);

CREATE TABLE `groups` (
`number` int(11) NOT NULL DEFAULT '0',
`grp` int(11) NOT NULL DEFAULT '0',
`processed` tinyint(1) DEFAULT NULL,
PRIMARY KEY (`number`,`grp`),
KEY `grp` (`grp`)
);

insert into company (col1, col2) values
(1,'2,3,4'),
(2,'5,6'),
(3,'1,2,5'),
(4,'7,8'),
(5,'11,3'),
(6,'22,8');

现在是程序

use test;

drop procedure if exists group_it;
delimiter //

create procedure group_it ()
begin
declare current_group int default 0;
declare ids varchar(100);

-- clear out all data from before
update company set grp = null;
truncate groups;

main: loop
-- take one unmapped (new group)
set ids := null;
select col2 into ids from company where grp is null limit 1;
if ids is null then
leave main;
end if;
set current_group := current_group + 1;

-- put each value into groups table and mark as unprocessed
call split_string(ids, ',');
insert into groups select value, current_group, false from SplitValues;

-- while unprocessed value in groups
begin
declare unprocessed int;

unprocessed: loop
set unprocessed = null;
select number
into unprocessed
from groups
where not processed
limit 1;

if unprocessed is null then
leave unprocessed;
end if;

begin
-- find all rows in company that matches this group
declare row_id int;
declare ids2 varchar(100);

declare cur2_done boolean;
declare cur2 cursor for
select col1, col2
from company
where col2 regexp concat('^', unprocessed, '$')
or col2 regexp concat('^', unprocessed, ',')
or col2 regexp concat(',', unprocessed, '$')
or col2 regexp concat(',', unprocessed, ',');

declare continue handler for not found set cur2_done := true;

open cur2;
numbers: loop
set cur2_done := false;
fetch cur2 into row_id, ids2;
if cur2_done then
close cur2;
leave numbers;
end if;

update company set grp = current_group where col1 = row_id;
-- add all new values to groups marked as unprocessed
call split_string(ids2, ',');
insert ignore into groups select value, current_group, false from SplitValues;
end loop numbers;
update groups set processed = true where number = unprocessed;
end;
end loop unprocessed;
end;
end loop main;
end//

delimiter ;

我是 Jay Pipes split_string

DELIMITER //

DROP PROCEDURE IF EXISTS split_string //
CREATE PROCEDURE split_string (
IN input TEXT
, IN `delimiter` VARCHAR(10)
)
SQL SECURITY INVOKER
COMMENT
'Splits a supplied string using using the given delimiter,
placing values in a temporary table'
BEGIN
DECLARE cur_position INT DEFAULT 1 ;
DECLARE remainder TEXT;
DECLARE cur_string VARCHAR(1000);
DECLARE delimiter_length TINYINT UNSIGNED;

DROP TEMPORARY TABLE IF EXISTS SplitValues;
CREATE TEMPORARY TABLE SplitValues (
value VARCHAR(1000) NOT NULL PRIMARY KEY
) ENGINE=MyISAM;

SET remainder = input;
SET delimiter_length = CHAR_LENGTH(delimiter);

WHILE CHAR_LENGTH(remainder) > 0 AND cur_position > 0 DO
SET cur_position = INSTR(remainder, `delimiter`);
IF cur_position = 0 THEN
SET cur_string = remainder;
ELSE
SET cur_string = LEFT(remainder, cur_position - 1);
END IF;
IF TRIM(cur_string) != '' THEN
INSERT INTO SplitValues VALUES (cur_string);
END IF;
SET remainder = SUBSTRING(remainder, cur_position + delimiter_length);
END WHILE;

END //

DELIMITER ;

关于mysql - 在公共(public)数据上对逗号分隔值进行分组,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9950216/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com