代码之家  ›  专栏  ›  技术社区  ›  X-Istence

按列名排序的MySQL随机行

  •  2
  • X-Istence  · 技术社区  · 16 年前

    原始问题:

    我目前正在使用Zend框架 Zend_Db_* ,我从表中选择三个随机行:

    $category->getTable()->select()->order(new Zend_Db_Expr('RAND()'))->limit('3')
    

    在哪里? $category 是一个 Zend_Db_Table_Row . 我想随机抽取三行,但这三行按列的顺序排列 name .

    改变 ->order() 对以下方面没有影响:

    ->order(array(new Zend_Db_Expr('RAND()'), 'name ASC'))
    

    因为条目仍然是无序的,仍然是随机的。

    Zend框架解决方案非常感谢,但我可以调整其他解决方案以适应我的项目。


    我知道使用rand()的伸缩性问题,数据库永远不会变得足够大,以致于成为一个问题,我不必担心维护它,机器人会,因为我早就死了!-P


    回答

    对于那些想知道这是如何使用zend_db_select最终完成的人来说,这就是在zend_db_select(我使用 $category->findDefault_Model_projects() 以查找依赖行集,但这不允许我使用select()作为子select,直到 ZF-6461 解决了这个问题,我坚持自己的观点):

    $projects = new Default_Model_Projects();
    $subselect = $projects->select()->order(new Zend_Db_Expr('RAND()'))->limit('3')->where('cid = ?', $category->id, Zend_Db::INT_TYPE);
    $db = $projects->getAdapter();
    $select = $db->select()->from(array("c" => new Zend_Db_Expr("({$subselect})")))->order('name');
    
    $stmt = $select->query();
    $projects = $stmt->fetchAll();
    

    生成的SQL是:

    SELECT `c`.* FROM (SELECT `projects`.* FROM `projects` WHERE (cid = 1) ORDER BY RAND() LIMIT 3) AS `c` ORDER BY `name` ASC
    

    从那里$projects包含了标准行集,可以像其他数据库查询一样迭代,它唯一不做的就是将其粘贴到特定于表的行/行集类中,这样可能会有其缺点。

    4 回复  |  直到 13 年前
        1
  •  4
  •   Adam Byrtek    16 年前

    您的初始解决方案不正确,因为此查询将为每一行生成一个随机值,并根据该值对行进行排序,仅当随机值相等(这是极不可能的)时才按名称排序。

    这个问题可以通过下面这样的子查询来解决

    select * from (select * from categories order by rand() limit 3) c order by name
    

    我要把这个翻译成Zend_-DB语言。

        2
  •  1
  •   Martin The Genius    13 年前
    $subQuery = $this->select()->from('picture')->order(new Zend_Db_Expr('RAND()'))->limit(count($this->selectAll()));
    $select->setIntegrityCheck(false)
           ->from($subQuery);
    

    这就是我所做的,它起作用了。干杯!

        3
  •  0
  •   gnarf    16 年前

    为什么不创建一个按名称对数据排序的行集子类函数呢?

        4
  •  0
  •   Richard Knop    16 年前

    试试这个:

    $select = $this->select();
    $select->order('RAND(), name');
    $select->limit(3);
    return $this->fetchAll($select);
    

    这对我来说很有用,所以也应该对你有用。