PHP 一个sql问题
时间:2010-09-15 来源:gaoqinlei96
这两天遇到一个sql问题跟大家分享一下,其中的逻辑是这样的。
有一个会员发布的信息表,在这个表里有会员ID,信息ID,创建时间等字段。
现在有一个需求是读出来这个表里的最新的16条信息,这是其中的一个条件,但是为了防止
会员刷屏每个会员的最新的信息最多只能显示3条。
也就是2个条件:
条件1:查询表里最新的16条
条件2:每个会员最多出现三条
我就开始构思sql语句,试了半天也没能实现。后来想貌似一句sql实现不了,但是我多条sql也没很理想的实现。
哎,无奈了。。。。读出来用程序foreach吧,下面是我实现的方法,一大堆的程序代码。。。
PHP代码:
函数: get_data函数返回一个查询完后的结果,数组类型 member_info16函数是处理结果集数组
表字段:guid 主键-自动增长,subtype 信息类型,owner_guid 会员ID,time_created 创建时间
变量: $results 是最后结果
$results = get_data("select guid,subtype,owner_guid,time_created from itv_entities as a where subtype in (11,15,17) order by time_created desc limit 30"); //先查询出来30条信息
$results_t = member_info16($results); //经过member_info16函数,返回guid数组
$count_t = count($results_t); //获得经过筛选后剩余多少条信息
$resutlts_t2 = array();
if($count_t<16){ //小于16条的时候再上数据库里去取剩余的
sort($results_t,SORT_NUMERIC);
$num_limit = 16-$count_t;
$min_guid = $results_t[0];
$results_two = get_data("select guid,subtype,owner_guid,time_created from itv_entities as a where subtype in (11,15,17) and guid<{$min_guid} order by time_created desc limit {$num_limit}");
$resutlts_t2 = member_info16($results_two);
}elseif($count_t>16){ //大于16条后用rsort逆向排序,把多余的删除掉
rsort($results_t,SORT_NUMERIC);
$num_limit = $count_t-16;
for($i=0;$i<$num_limit;$i++){
array_pop($results_t);
}
}
$results_value = implode(',',array_merge($results_t,$resutlts_t2)); //合并2个数组,得到最后的结果
$results = null;
$results = get_data("select guid,subtype from itv_entities where guid in ({$results_value}) order by time_created desc"); //传给最后的sql,直接读取
function member_info16($results){
foreach ($results as $result){
$result=(array)$result;
if(count($result_s[$result['owner_guid']])<3){ //如果这个会员的信息没有超过3条就存在数组里
$result_s[$result['owner_guid']][]=$result;
}
}
foreach ($result_s as $var){ //二次foreach循环,获得主键guid
foreach ($var as $key){
$results_t[]=$key['guid'];
}
}
return $results_t; //返回数组
}
总结:虽然是用程序的方式实现了,但还不是很理想,查询了至少2次数据库再加上foreach,速度上有点慢,显然不是明智的解决办法
不过对于数据量少的可以凑活着用。。。
有一个会员发布的信息表,在这个表里有会员ID,信息ID,创建时间等字段。
现在有一个需求是读出来这个表里的最新的16条信息,这是其中的一个条件,但是为了防止
会员刷屏每个会员的最新的信息最多只能显示3条。
也就是2个条件:
条件1:查询表里最新的16条
条件2:每个会员最多出现三条
我就开始构思sql语句,试了半天也没能实现。后来想貌似一句sql实现不了,但是我多条sql也没很理想的实现。
哎,无奈了。。。。读出来用程序foreach吧,下面是我实现的方法,一大堆的程序代码。。。
PHP代码:
函数: get_data函数返回一个查询完后的结果,数组类型 member_info16函数是处理结果集数组
表字段:guid 主键-自动增长,subtype 信息类型,owner_guid 会员ID,time_created 创建时间
变量: $results 是最后结果
$results = get_data("select guid,subtype,owner_guid,time_created from itv_entities as a where subtype in (11,15,17) order by time_created desc limit 30"); //先查询出来30条信息
$results_t = member_info16($results); //经过member_info16函数,返回guid数组
$count_t = count($results_t); //获得经过筛选后剩余多少条信息
$resutlts_t2 = array();
if($count_t<16){ //小于16条的时候再上数据库里去取剩余的
sort($results_t,SORT_NUMERIC);
$num_limit = 16-$count_t;
$min_guid = $results_t[0];
$results_two = get_data("select guid,subtype,owner_guid,time_created from itv_entities as a where subtype in (11,15,17) and guid<{$min_guid} order by time_created desc limit {$num_limit}");
$resutlts_t2 = member_info16($results_two);
}elseif($count_t>16){ //大于16条后用rsort逆向排序,把多余的删除掉
rsort($results_t,SORT_NUMERIC);
$num_limit = $count_t-16;
for($i=0;$i<$num_limit;$i++){
array_pop($results_t);
}
}
$results_value = implode(',',array_merge($results_t,$resutlts_t2)); //合并2个数组,得到最后的结果
$results = null;
$results = get_data("select guid,subtype from itv_entities where guid in ({$results_value}) order by time_created desc"); //传给最后的sql,直接读取
function member_info16($results){
foreach ($results as $result){
$result=(array)$result;
if(count($result_s[$result['owner_guid']])<3){ //如果这个会员的信息没有超过3条就存在数组里
$result_s[$result['owner_guid']][]=$result;
}
}
foreach ($result_s as $var){ //二次foreach循环,获得主键guid
foreach ($var as $key){
$results_t[]=$key['guid'];
}
}
return $results_t; //返回数组
}
总结:虽然是用程序的方式实现了,但还不是很理想,查询了至少2次数据库再加上foreach,速度上有点慢,显然不是明智的解决办法
不过对于数据量少的可以凑活着用。。。
相关阅读 更多 +