2010-10-13 2 views
2

У меня есть одна таблица магазина идентификатор сообщения и это теги, как:разделить ключевые слова для пост PHP MySQL

Post_id | Tags 
-------------------------------------- 
1  | keyword1,keyword2,keyword3 

Я хочу петлю, хотя каждый ряд в этой таблице и сделать:

  • положить keyword1, keyword2, в новом ключевого слово 3 таблицы: Еогеаспе

    word_id | word_value 
    ------------------------- 
        1  | keyword1 
        2  | keyword2  
        3  | keyword3 
    
  • прибудет mysql_insert_id() (или существует word_id если word_value уже там), а затем положить в новую таблицу, как:

    post_id | word_id 
    ------------------ 
    1  | 1  
    1  | 2  
    1  | 3 
    

Я с помощью PHP и MySQL для делать эту задачу, но это медленно. У кого-нибудь есть хорошая идея?

+0

можете ли вы разместить свой скрипт здесь, который выполняет эту задачу? Также, сколько записей в оригинальной таблице? –

+0

OP не был на сайте с =/ –

ответ

4

сделать что-то вроде этого:

-- TABLES 

drop table if exists post_tags; 
create table post_tags 
(
post_id int unsigned not null auto_increment primary key, 
tags_csv varchar(1024) not null 
) 
engine=innodb; 

drop table if exists keywords; 
create table keywords 
(
keyword_id mediumint unsigned not null auto_increment primary key, 
name varchar(255) unique not null 
) 
engine=innodb; 


-- optimised for queries such as - select all posts that have keyword 3 

drop table if exists post_keywords; 
create table post_keywords 
(
keyword_id mediumint unsigned not null, 
post_id int unsigned not null, 
primary key (keyword_id, post_id), -- clustered composite PK ! 
key (post_id) 
) 
engine=innodb; 

-- STORED PROCEDURES 


drop procedure if exists normalise_post_tags; 

delimiter # 

create procedure normalise_post_tags() 
proc_main:begin 

declare v_cursor_done tinyint unsigned default 0; 

-- watch out for variable names that have the same names as fields !! 

declare v_post_id int unsigned; 
declare v_tags_csv varchar(1024); 
declare v_keyword varchar(255); 

declare v_keyword_id mediumint unsigned; 

declare v_tags_done tinyint unsigned; 
declare v_tags_idx int unsigned; 

declare v_cursor cursor for select post_id, tags_csv from post_tags order by post_id; 
declare continue handler for not found set v_cursor_done = 1; 

set autocommit = 0; 

open v_cursor; 
repeat 

    fetch v_cursor into v_post_id, v_tags_csv; 

    -- split the out the v_tags_csv and insert 

    set v_tags_done = 0;  
    set v_tags_idx = 1; 

    while not v_tags_done do 

    set v_keyword = substring(v_tags_csv, v_tags_idx, 
     if(locate(',', v_tags_csv, v_tags_idx) > 0, 
     locate(',', v_tags_csv, v_tags_idx) - v_tags_idx, 
     length(v_tags_csv))); 

     if length(v_keyword) > 0 then 

     set v_tags_idx = v_tags_idx + length(v_keyword) + 1; 

     set v_keyword = trim(v_keyword); 

     -- add the keyword if it doesnt already exist 
     insert ignore into keywords (name) values (v_keyword); 

     select keyword_id into v_keyword_id from keywords where name = v_keyword; 

     -- add the post_keywords 
     insert ignore into post_keywords (keyword_id, post_id) values (v_keyword_id, v_post_id); 

     else 
     set v_tags_done = 1; 
     end if; 

    end while; 

until v_cursor_done end repeat; 

close v_cursor; 

commit; 

end proc_main # 


delimiter ; 


-- TEST DATA 

insert into post_tags (tags_csv) values 
('keyword1,keyword2,keyword3'), 
('keyword1,keyword5'), 
('keyword4,keyword3,keyword6,keyword1'); 

-- TESTING 

call normalise_post_tags(); 

select * from post_tags order by post_id; 
select * from keywords order by keyword_id; 
select * from post_keywords order by keyword_id, post_id; 
+1

Это работает очень хорошо. Это спасло меня так много времени, я бы хотел, чтобы я мог продвигать его больше ... – CMPalmer

0

для каждого ключевого слова, сделать

insert into newtable (id, keyword) select id, 'aKeyword' from oldtable where oldtable.keywords like '%aKeyword%' 

если oldtable.keywords просто VARCHAR или

insert into newtable (id, keyword) select id, 'aKeyword' from oldtable where FIND_IN_SET('aKeyword',keywords)>0 

если это тип SET ,