ऐसा करना संभव है लेकिन मुझे यकीन नहीं है कि यह आपकी बहुत बड़ी मेज पर कितना समय लेगा। मुझे लगता है कि आपको सभी समूहों को धारण करने वाली एक नई तालिका बनाने की अनुमति है और समूह कॉलम आबादी के रूप में संख्याएं हैं।
साथ ही, यह लाइव टेबल पर नहीं चल सकता। इसे लिखना संभव नहीं है इसलिए यह मेरे डिजाइन की सीमा नहीं है। इस बारे में सोचें कि क्या होगा यदि आप मान 7 और '6,7' के साथ एक नई पंक्ति जोड़ते हैं, जो समूह 1 और 2 को पाट देगा और सारा काम छोड़ना होगा।
हर बार तालिका में अतिरिक्त होने पर इस खरीद को फिर से चलाने की आवश्यकता होती है। यदि यह स्वीकार्य नहीं है तो इसे एक बार चलाएं और फिर इसे ट्रिगर से बदलें जो मूल्यों को बनाए रखता है और जरूरत पड़ने पर समूहों को मर्ज करता है।
यहाँ प्रक्रिया है। यह कुछ मॉडर्नाइजेशन से लाभान्वित हो सकता है लेकिन यह काम करता है। मैंने जे पाइप्स split_string लिया है कार्य किया और इसे शामिल किया।
पहले डीडीएल और कुछ परीक्षण डेटा
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 ;
यह जे पाइप्स स्प्लिट_स्ट्रिंग है
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 ;