mysql关于列转行的想法,以及列求乘集

mysql列转行可以通过concat,先分组然后连接。

show VARIABLES like '%group%'
set @@group_concat_max_len = 10240
select @@group_concat_max_len

SELECT GROUP_CONCAT(goods_id),1 as lzh FROM ts_goods
WHERE ts_goods.cat_id_1 = 336 OR ts_goods.cat_id_2 = 336 OR ts_goods.cat_id_3 = 336
group by lzh

这里默认的限制是1024字节,可以通过set调整一下。

想到这个的原因是mysql在执行in操作的时候,有时候外层表的数据量巨大,使用in子查询之后不是用外层索引,但是直接的使用字符串拼接会使用索引。

这里还有一个问题,就是in的子查询的where语句没有索引与有索引差别也挺大,使用exlpain extended查看的时候不添加索引会全表扫描外层表。

SELECT DISTINCT order_id FROM ts_order_goods  WHERE goods_id in
    (
        SELECT goods_id FROM ts_goods
        WHERE ts_goods.cat_id_1 = 336 OR ts_goods.cat_id_2 = 336 OR ts_goods.cat_id_3 = 336
    )

这里cat_id_1,cat_id_2,cat_id_3,没有索引的话ts_order_goods会all扫描100w行,如果有索引会使用index_marge,只有2k行。

而且上面的语句只是一个大查询的一个子查询,而且大查询的其他条件对这个子查询的优化结果也不同,mysql内部的优化机制挺复杂的,会根据整个执行的语句优化,根据结果集做优化判断。

上面的方法可以用到存储过程里面,这样就不用php去外层查询两次数据库,并拼接了。

CREATE PROCEDURE GetUsersDynamic(WhereCondition varchar(500),OrderByExpress varchar(100))
begin
declare stmt varchar(2000);
if LENGTH(OrderbyExpress)>0 then
begin
     set @sqlstr=concat('select id,name,password,age,getdate(adddate) as AddDate from users where ',WhereCondition,' order by ',OrderByExpress);
end;
else
begin
     set @sqlstr=concat('select id,name,password,age,getdate(adddate) as AddDate from users where ',WhereCondition);
end;
end if;
prepare stmt from @sqlstr;
execute stmt;
end;

注意,mysql里面varchar的长度是有限制的,所以不能拼接过长的数据。mysql的in可以转为join,或者exist。

 

求乘集的方法是临时想的,主要是通过log与power,因为logA+logB = logAB。

SELECT pow(2, sum(log2(b))) from 
(select 2 as b union select 3 union select 4) as t

这样可以得到2*3*4=24

posted on 2014-06-06 14:11  kudosharry  阅读(457)  评论(0编辑  收藏  举报

导航