mysql - yii 分页问题尝试使用 2 个标准

标签 mysql yii pagination

免责声明我是自学成才的。通过阅读论坛了解了 php 的基本知识。我是一个 sql 新手,对 yii 几乎一无所知。

我有一个 Controller ,可以显示我们网上商店中的产品。我希望缺货的产品显示在最后几页上。

我知道我可以按库存数量排序,但希望每次重新加载页面时库存产品都会更改顺序。

我的解决方案(可能是错误的,但有点有效)是运行两个查询。一种是有库存的产品,随机排序。缺货产品也随机订购。然后我合并两个结果数组。使用下面的代码已经完成了很多工作(尽管我觉得一定有比运行两个查询更有效的方法)。

问题是这会扰乱分页。每个返回的产品都列在同一页面上,更改页面会显示相同的结果。据我所知,分页一次仅适用于 1 个 CDbCriteria。我已经查看了 CPagination 的 yii 文档来解决这个问题,但没有取得任何进展。

        $criteria=new CDbCriteria;
        $criteria->alias = 'Product';
        $criteria->addCondition('(inventory_avail>0 OR inventoried=0)');
        $criteria->addCondition('Product.parent IS NULL');
        $criteria->addCondition('web=1');
        $criteria->addCondition('current=1');
        $criteria->addCondition('sell>sell_web');
        $criteria->order = 'RAND()';

        $criteria2=new CDbCriteria;
        $criteria2->alias = 'Product';
        $criteria2->addCondition('(inventory_avail<1 AND inventoried=1)');
        $criteria2->addCondition('Product.parent IS NULL');
        $criteria2->addCondition('web=1');
        $criteria2->addCondition('current=1');
        $criteria2->addCondition('sell>sell_web');
        $criteria2->order = 'RAND()';   

        $crit1=Product::model()->findAll($criteria);
        $crit2=Product::model()->findAll($criteria2);
        $models=array_merge($crit1,$crit2);                 

        //I know there is something wrong here, no idea how to fix it..
        $count=Product::model()->count($criteria);
        $pages=new CPagination($count);
        //results per page
        $pages->pageSize=30;
        $pages->applyLimit($criteria);

        $this->render('index', array(
        'models' => $models,
            'pages' => $pages
            ));

显然我已经不知所措了。任何帮助将不胜感激。

编辑:

我认为包含有库存和缺货商品的第三个 CDbCriteria 可用于分页(因为它将包含与前 2 个商品的组合结果相同数量的产品)。所以我尝试添加这个(criteria1和criteria2保持不变):

        $criteria3=new CDbCriteria;
        $criteria3->alias = 'Product';
        //$criteria3->addCondition('(inventory_avail>0 OR inventoried=0)');
        $criteria3->addCondition('Product.parent IS NULL');
        $criteria3->addCondition('web=1');
        $criteria3->addCondition('current=1');
        $criteria3->addCondition('sell>sell_web');
        //$criteria3->order = 'RAND()';

        $crit1=Product::model()->findAll($criteria);
        $crit2=Product::model()->findAll($criteria2);
        $models=array_merge($crit1,$crit2);                 

        $count=Product::model()->count($criteria3);
        $pages=new CPagination($count);
        //results per page
        $pages->pageSize=30;
        $pages->applyLimit($criteria3);

        $crit1=Product::model()->findAll($criteria);
        $crit2=Product::model()->findAll($criteria2);
        $models=array_merge($crit1,$crit2); 

        $this->render('index', array(
        'models' => $models,
            'pages' => $pages
            ));  

我确信我在这里遗漏了一些非常明显的东西...已经搜索了一整天却一无所获。

最佳答案

因此,在我看来,您正在遇到自然语言查询构建器框架的潜在缺点之一。当您尝试使用“开箱即用”的方法来构建查询时,他们可以让您思考如何处理陷入困境的 SQL 问题。有时您可能需要考虑使用大多数框架都提供的原始 SQL 查询功能,以便最好地解决您的问题。

因此,让我们从基本 SQL 开始,了解我建议您如何解决问题。您可以将其应用到查询构建器样式中(如果可能)或进行原始查询。

您可以轻松地形成一个计算字段来表示二进制库存状态以进行排序。然后再按另一个标准排序。

SELECT
    field1,
    field2,
    /* other fields */
    IF(inventory_avail > 0, 1, 0) AS in_inventory
FROM product
WHERE /* where conditions */
ORDER BY
    in_inventory DESC, /* sort items in inventory first */
    other_field_to_sort ASC /* other sort criteria */
LIMIT ?, ? /* pagination row limit and offset */

请注意,此方法仅返回您需要显示的数据行。您将放弃当前在应用程序中执行大量工作来合并记录集等的方法。

我确实质疑将 RAND() 用于分页目的,因为这样做会产生当用户分页时可能出现在一页又一页的产品,而其他产品可能不会显示在全部。或者您需要在应用程序中添加一些额外的复杂性,以某种方式跟踪每个特定用户的整个结果集的“随机”版本。因此,分页结果显示的顺序随机化确实很不寻常。

我知道您提到您可能希望在“第一页”上向用户显示随机 View 。如果这是一个愿望,那是可以的,但也许您可以将该特定 View 与产品列表的更广泛的分页 View 分离或区分,以免最终用户对看似不可预测的分页界面感到困惑。

在 ORDER BY 子句中,您应该始终有足够的排序条件,最终(最具体的)条件将保证您获得可预测的订单结果。通常,这意味着您必须包含自动增量主键字段或为行提供唯一性的类似字段。

举例来说,我可以让用户按价格对商品进行排序,但您显然仍然希望首先显示所有库存商品。现在假设您有 100K 种产品,这样当按价格订购时,您将拥有许多具有共同价格的产品“页面”

如果您使用它来订购:

ORDER BY in_inventory DESC, price ASC

您仍然可能遇到用户在页面之间导航时重复看到相同产品的问题,因为没有给出比价格更具体的标准,并且无法保证超出该标准的订购。

您可能想做类似的事情:

ORDER BY in_inventory DESC, price ASC, unique_id ASC

这样的顺序是完全可预测的(即使用户可能甚至不知道有通过唯一 ID 进行排序)。

关于mysql - yii 分页问题尝试使用 2 个标准,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40117442/

相关文章:

sql - 整理出三个第一次出现的属性

MySQL连接查询问题

MYSQL 查询使用 AND OR

optimization - 我应该在 sitemap.xml 中包含分页结果吗?

mysql - MySQL中使用UNION时如何进行分页?

go - 如何使用 bigtable Go 客户端支持分页?

mysql - 运行具有不同数据库但使用相同用户数据库的多个网站

php - Yii PHP 应用程序的迁移

php - 在 Yii 中循环使用事务

Yii View,替换 CGridView 中的一些数据库值