限制每个类别的结果数量,建议需要

时间:2013-06-07 19:47:02

标签: php mysql shuffle

我有这段代码

<?php
function Random($numchar)  
{  
$categories = "83 76 168 102";  
$array=explode(" ",$categories);  
shuffle($array);  
$newstring = implode($array,",");
return substr($newstring, 0, $numchar);  

}
$numbers = Random(216);
$res = str_replace(",","','",$numbers);
$cats = '\''.$res.'\'';
$news = mysql_query("SELECT 
item.id AS itemid, 
item.cid AS itemcid, 
SUBSTRING_INDEX(item.url, '/', 3) AS itemurl, 
item.title AS itemtitle, 
item.top AS itemtop, 
images.id AS imgid, 
images.img AS imagesimg, 
images.item_id AS imagesitemid,
folders.id AS foldersid,
channels.id AS channelsid,
channels.parent AS channelsparent
FROM item, images, folders, channels 
WHERE 
item.id = images.item_id
AND item.cid = channels.id
AND channels.parent = folders.id
AND channels.parent = '$cat'
AND FIELD(item.cid, $cats)
ORDER BY 
itemtop DESC, RAND(), images.item_id DESC 
LIMIT 20");

?>

每次刷新页面时,代码都会从变量$ categories中定义的类别中返回20个项目。我想只显示每个类别中的5个项目。是否可以按照我的意图使用单个查询?我想腾出空间,所以所有类别的项目都可以平等显示。

我还有其他方法可以优化查询吗?

2 个答案:

答案 0 :(得分:1)

为了从每个类别中获取5个项目,您必须对每个类别运行单独的子查询,限制为5,然后将它们组合在一起。这是一个例子:

SELECT
  *
FROM (
  (SELECT
    item.id AS itemid, 
    item.cid AS itemcid, 
    SUBSTRING_INDEX(item.url, '/', 3) AS itemurl, 
    item.title AS itemtitle, 
    item.top AS itemtop, 
    images.id AS imgid, 
    images.img AS imagesimg, 
    images.item_id AS imagesitemid,
    folders.id AS foldersid,
    channels.id AS channelsid,
    channels.parent AS channelsparent
  FROM
    item,
    images,
    folders,
    channels
  WHERE 
    item.id = images.item_id
    AND item.cid = channels.id
    AND channels.parent = folders.id
    AND channels.parent = '$cat[0]'
    AND FIELD(item.cid, $cats[0])
  LIMIT 5)

  UNION ALL

  (SELECT
    item.id AS itemid, 
    item.cid AS itemcid, 
    SUBSTRING_INDEX(item.url, '/', 3) AS itemurl, 
    item.title AS itemtitle, 
    item.top AS itemtop, 
    images.id AS imgid, 
    images.img AS imagesimg, 
    images.item_id AS imagesitemid,
    folders.id AS foldersid,
    channels.id AS channelsid,
    channels.parent AS channelsparent
  FROM
    item,
    images,
    folders,
    channels
  WHERE 
    item.id = images.item_id
    AND item.cid = channels.id
    AND channels.parent = folders.id
    AND channels.parent = '$cat[1]'
    AND FIELD(item.cid, $cats[1])
  LIMIT 5)

  UNION ALL

  (SELECT
    item.id AS itemid, 
    item.cid AS itemcid, 
    SUBSTRING_INDEX(item.url, '/', 3) AS itemurl, 
    item.title AS itemtitle, 
    item.top AS itemtop, 
    images.id AS imgid, 
    images.img AS imagesimg, 
    images.item_id AS imagesitemid,
    folders.id AS foldersid,
    channels.id AS channelsid,
    channels.parent AS channelsparent
  FROM
    item,
    images,
    folders,
    channels
  WHERE 
    item.id = images.item_id
    AND item.cid = channels.id
    AND channels.parent = folders.id
    AND channels.parent = '$cat[2]'
    AND FIELD(item.cid, $cats[2])
  LIMIT 5)
)sub_query

ORDER BY 
  itemtop DESC, RAND(), sub_query.item_id DESC

您可能希望在子查询中添加订单,以定义为每个类别返回的5个订单。您可能还需要重新定义$cat的定义方式。希望这会有所帮助。

答案 1 :(得分:0)

你可以尝试使用用户变量...不确定如何/如果php将处理它,但使用原始的sql这样的东西应该工作(没有测试,但你应该明白,请参阅http://www.xaprb.com/blog/2006/12/07/how-to-select-the-firstleastmax-row-per-group-in-sql/ for更多细节):

set @num := 0, @cid := '';

SELECT 
item.id AS itemid, 
item.cid AS itemcid, 
SUBSTRING_INDEX(item.url, '/', 3) AS itemurl, 
item.title AS itemtitle, 
item.top AS itemtop, 
images.id AS imgid, 
images.img AS imagesimg, 
images.item_id AS imagesitemid,
folders.id AS foldersid,
channels.id AS channelsid,
channels.parent AS channelsparent,
@num := if(@cid = item.cid, @num + 1, 1) as row_number,
@cid := cid as dummy
FROM item, images, folders, channels 
WHERE 
item.id = images.item_id
AND item.cid = channels.id
AND channels.parent = folders.id
AND channels.parent = '$cat'
AND FIELD(item.cid, $cats)
ORDER BY 
itemtop DESC GROUP, RAND(), images.item_id DESC
GROUP BY item.id, item.cid, item.title
having row_number <= 5;