实际问题是
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表就一样了
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表就一样了
select * from thenew where bookid=227
替换成视图名
是个传入参数 会变的
而且我估计建视图他也是执行两次查询吧
毕竟视图本来就是一个查询
我们每次调用视图 实际上是执行了一次定义视图的查询吧(我是这么理解的,不知道有没有错)
我昨天试call test(227) 代替那个子查询
不行
不能用存储过程动态生成SQL语句,呵呵
这个不是速度的问题,问题是他执行两次 rand()就执行了两次
这样用来连接的两个表的chapterid字段就不一样了
内存中是可以建临时表的
还有一种是,表结构非临时(即存在磁盘中),但数据存在内存里,重启机器后数据丢失,表还在。
即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
内存表还没有用过,学习了,自己解决更好。
就是那个内存表是公用的
并发执行那个存储过程的时候 mysql会自动锁定那个内存表吗
还是要我在存储过程里显式的给那个内存表加锁?