实际问题是
SELECT * FROM (select * from thenew where bookid=227) A LEFT JOIN 
(select * from thenew where bookid=227) B ON A.chaptername=B.chaptername 
AND A.chapterid>=B.chapterid
GROUP BY A.chaptername,A.updatetime HAVING COUNT(*) <=2 
ORDER BY b.updatetime desc,A.chaptername,a.updatetime limit 20简化了问题(一般看这个就可以了)
SELECT * FROM (select * from thenew where bookid=227) A LEFT JOIN 
(select * from thenew where bookid=227) B ON A.chaptername=B.chaptername 
AND A.chapterid>=B.chapterid
GROUP BY A.chaptername,A.updatetime HAVING COUNT(*) <=2 子查询中的thenew 是个视图,thenew 中的字段chapterid是函数rand()
现在问题是这个子查询每执行一次chapterid就会变化,那样外层查询中的A,B表就不一样了,
所以有没有办法让子查询只执行一次,这样A,B表就一样了

解决方案 »

  1.   

    建立视图嘛,
    select * from thenew where bookid=227
    替换成视图名
      

  2.   

    不行 bookid=227 
    是个传入参数 会变的
    而且我估计建视图他也是执行两次查询吧
    毕竟视图本来就是一个查询
    我们每次调用视图 实际上是执行了一次定义视图的查询吧(我是这么理解的,不知道有没有错)
      

  3.   

    存储过程没法当作子查询使用啊
    我昨天试call test(227) 代替那个子查询
    不行
      

  4.   

    mysql能不能在内存中建临时表?
      

  5.   


    不能用存储过程动态生成SQL语句,呵呵
      

  6.   


    这个不是速度的问题,问题是他执行两次 rand()就执行了两次
    这样用来连接的两个表的chapterid字段就不一样了
      

  7.   

    搞定了
    内存中是可以建临时表的
    还有一种是,表结构非临时(即存在磁盘中),但数据存在内存里,重启机器后数据丢失,表还在。
    即MEMORY (HEAP)存储引擎
    下面把自己的解决方案贴出来
    --一下是真正实现随机出现记录的
    --视图thenew
    create view thenew(bookid,chaptername,chapterurl,updatetime,webname,chapterid)
    as
    select bookid,chaptername,chapterurl,updatetime,webname,rand() from edu_thenew
    --先建立一个数据存放在内存的表,bookid无所谓,主要要复制视图thenew的结构
    --注意,这里不能使用临时表TEMPORARY,使用的话报错can't reopen A
    create table tempThenew ENGINE=MEMORY select * from thenew where bookid=227;
    --实际上创建完DDL是,用以下创建也可
    CREATE TABLE `tempthenew` (
      `bookid` INTEGER(11) UNSIGNED NOT NULL,
      `chaptername` VARCHAR(100) COLLATE gbk_chinese_ci NOT NULL DEFAULT '',
      `chapterurl` VARCHAR(500) COLLATE gbk_chinese_ci NOT NULL DEFAULT '',
      `updatetime` DATETIME NOT NULL,
      `webname` VARCHAR(20) COLLATE gbk_chinese_ci NOT NULL DEFAULT '',
      `chapterid` DOUBLE NOT NULL DEFAULT '0'
    )ENGINE=HEAP
    CHARACTER SET 'gbk' COLLATE 'gbk_chinese_ci';--然后以后每次需要显示页面的时候调用这个存储过程就可以了
    DROP PROCEDURE IF EXISTS `c`;
    CREATE PROCEDURE `c`(
    IN bookid_in INTEGER(11) #书ID    
        )
        DETERMINISTIC
        CONTAINS SQL
        SQL SECURITY DEFINER
        COMMENT ''
    BEGIN
    TRUNCATE tempThenew;
    insert into tempThenew select * from thenew where bookid=bookid_in;SELECT * FROM tempThenew A inner JOIN tempThenew B ON A.chaptername=B.chaptername 
    AND A.chapterid>=B.chapterid
    GROUP BY A.chaptername,A.updatetime HAVING COUNT(*) <=5 
    ORDER BY B.updatetime desc,A.chaptername limit 20;
    END;#以下为调用示例
    #call c(227)
    看这好像挺麻烦的,最后测试调用性能还行,我自己的破机器执行call c(227)也就144ms。
    实际上以上功能是实现--将重复了M次的记录显示出N条,并且这显示出来N条记录是随机从M条记录中选取的,
    即每次查询结果不一样
    如果只想将重复了M次的记录显示出N条,不需要随机抽取,就不用向我上面这么麻烦了
    直接把存储过程里的select语句改改就成了
    不过按我上面的方法还有个好处就是节省了辅助列chapterid占用的磁盘空间
    想省空间的话,就算你不要随机显示功能,还是可以用上面这个方法的^_^
    再次对WWWWA的热心帮助表示感谢!^_^另,这帖子的兄长帖子,这里有看不明白的可以参照下面这个帖子
    将重复了M次的记录显示N次的sql语句怎么写
    http://topic.csdn.net/u/20080920/15/1b4cedef-f98d-4af9-8c76-d541ade14632.html
      

  8.   

    不错,原来还想用动态生成SQL语句的方法,用SP中的IN参数就OK了,
    内存表还没有用过,学习了,自己解决更好。
      

  9.   

    其实还有一个问题
    就是那个内存表是公用的
    并发执行那个存储过程的时候 mysql会自动锁定那个内存表吗
    还是要我在存储过程里显式的给那个内存表加锁?