统计需求:有多少本(完本)图书被完全阅读了?
mylogs表里放的是每天的阅读日志(分析Apache日志所得),book表里放的是图书的信息,比如某本书有多少章,作者,书名等等。写了如下的存储过程,
create procedure wanbens(in d int, in m int ,in y int)
begin
declare total_nums int default 0;
declare mxindexed int default 0;
declare mxindex int default 0;
declare bid varchar(20) default '';
declare tmp_bid int default 0;
declare i int default 0;
declare wbbook_nums int default 0; select count( distinct para_bookid ) into total_nums from mylogs where  log_day=d and log_month=m and log_year=y;

while i<total_nums do select para_bookid into bid from mylogs where para_bookid<>tmp_bid and log_day=d and log_month=m and log_year=y order by para_bookid limit 1; if bid <> tmp_bid then
set tmp_bid = 0;
select para_bookid, para_index into tmp_bid, mxindexed from mylogs where para_bookid=bid and log_day=d and log_month=m and log_year=y order by para_index desc limit 1; select  max_chapter into mxindex from book where bookid=tmp_bid limit 1; if mxindexed = mxindex then
set wbbook_nums = wbbook_nums+1;
end if;

end if;
set i = i+1;
set bid = 0;
end while;
select wbbook_nums;
end
但是call的时候,有死循环,谁知道为什么?以及有没有更好的办法来解决,比如使用temporary table或别的什么方法。

解决方案 »

  1.   

    DELIMITER $$
    create procedure wanbens(in d int, in m int ,in y int) 
    begin 
    END$$DELIMITER ;
      

  2.   

    好的,现在第一楼的那个存储过程,我重写了下,改用游标,如下:CREATE PROCEDURE wanbens(in d INT, in m INT ,in y INT)
    BEGIN DECLARE wbbook_nums INT; 
    DECLARE wbusr_nums INT;
    DECLARE tmp_bid VARCHAR(20);
    DECLARE tmp_phone VARCHAR(20);
    DECLARE tmp_phone1 VARCHAR(20);
    DECLARE mxed_index INT;
    DECLARE mx_index INT;
    DECLARE done INT DEFAULT 0;DECLARE cur1 CURSOR FOR SELECT para_bookid, max(para_index) as mai, phone FROM mylogs WHERE log_day=d AND log_month=m AND log_year=y GROUP BY para_bookid HAVING mai>0;OPEN cur1;REPEAT FETCH cur1 INTO tmp_bid,mxed_index,tmp_phone; SELECT max_chapter INTO mx_index FROM book  WHERE bookid LIKE CONCAT('%',tmp_bid,'%'); IF mx_index=mxed_index THEN
    SET wbbook_nums = wbbook_nums + 1;
    END IF; IF tmp_phone<>tmp_phone1 THEN
    SET wbusr_nums = wbusr_nums + 1;
    END IF;

    SET tmp_phone1 = tmp_phone;UNTIL done END REPEAT;CLOSE cur1;SELECT wbbook_nums, wbusr_nums;ENDmylogs表结构:drop table if exists mylogs;
    create table mylogs (
       log_year int(4) unsigned not null default 0, ##访问年
       log_month int(2) unsigned not null default 0, ##月份
       log_day int(2) unsigned not null default 0,  ##天
       log_period int(2) unsigned not null default 0, ##具体时间
       phone varchar(20) not null default '',  ##用户手机号
       para_a varchar(100) not null default '',
       para_c varchar(100) not null default '',
       para_bookid varchar(100) not null default '', ##用户访问的图书ID, 存储过程做的就是从这里取出一本书ID,取出用户阅读过的最大章节ID,
                                                             ##然后从book表中取出相同bookid的max_chapter,相比较,如果相同,说明该书被该用户完整
                                                              ##阅读了。   para_index varchar(100) not null default '', ##用户访问过的章节ID
       para_p varchar(100) not null default '',
       para_x varchar(100) not null default '',
       para_y varchar(100) not null default '',
       para_key varchar(255) not null default '',
       para_type varchar(100) not null default '',
       index_access enum('yes','no') not null default 'no',
       ua varchar(200) not null default ''

    engine=myisam 
    default charset=utf8
    partition by list(log_month) (
       partition p01 values in (1),
       partition p02 values in (2),
       partition p03 values in (3),
       partition p04 values in (4),
       partition p05 values in (5),
       partition p06 values in (6),
       partition p07 values in (7),
       partition p08 values in (8),
       partition p09 values in (9),
       partition p10 values in (10),
       partition p11 values in (11),
       partition p12 values in (12)
    );book表结构:CREATE TABLE `book` (
      `bookid` varchar(255) DEFAULT NULL,  ##在book表中,bookid唯一。
      `title` varchar(255) DEFAULT NULL,
      `book_category_zh` varchar(25) DEFAULT NULL,
      `book_category_en` varchar(10) DEFAULT NULL,
      `max_chapter` varchar(255) DEFAULT NULL,  ##该书的最大章节数,比如有20个章节,这个字段的值就是20
      `author` varchar(50) NOT NULL DEFAULT ''
    ) ENGINE=InnoDB DEFAULT CHARSET=utf8表字段的说明,上边已有,wanbens的作用就是统计某一天有多少本书被用户完全阅读了,至少是阅读了最后一个章节。
    应该说清楚了吧。
      

  3.   

    本帖最后由 ACMAIN_CHM 于 2009-05-20 19:13:00 编辑
      

  4.   

    本帖最后由 ACMAIN_CHM 于 2009-05-20 19:15:49 编辑
      

  5.   

    ACMAIN_CHM ,强人,SQL写得漂亮,并且解决问题!谢谢了。
      

  6.   

    但为什么是inner join呢?不是left join或right join?
      

  7.   

    可以用left join / right join 但没有什么意义啊。 你的读者读的书或者章节不存在?
      

  8.   


    由于新旧库的原因,是有一部分书不存在,不过,这些错误的数据就不要了,所以,还是应该用inner join 万分感谢,散分。