Zend_Db_Select 随机排序,兼容 mssql / mysql

Posted

技术标签:

【中文标题】Zend_Db_Select 随机排序,兼容 mssql / mysql【英文标题】:Zend_Db_Select order by random, compatible in mssql / mysql 【发布时间】:2010-12-01 06:07:49 【问题描述】:

好吧,情况就是这样,我有一个用 Zend_Framework 编写的应用程序,它同时兼容 mysql 和 MSSQL 作为后端。现在,ZF 非常擅长解决两种语言之间的许多 SQL 差异/差异,但我还没有弄清楚这一点。

目标是从表中随机选择1条记录,这是一个非常简单的语句。

这里有一个 select 语句的例子:

$sql = $db->select()
      ->from("table")
      ->order("rand()")
      ->limit(1);

这对于 MySQL 数据库表非常有效,因为 MySQL 的 sql 如下:

SELECT `table`.* FROM `table` ORDER BY rand() ASC

另一方面,现在 MSSQL 使用 newid() 函数进行随机化。

是否有某种帮助我可以传递给 order() 函数以使其意识到它必须使用正确的排序?我搜索了文档并在 zfforums 上找到了一些提示,但没有什么可靠的。

我确实找到了一件事情是:

ORDER BY RANDOM() not working - ZFForums.com

他们正在使用以下内容:

$res = $db->fetchAll(
'SELECT * FROM table ORDER BY :random',
array('random' => new Zend_Db_Expr('RANDOM()')
);

它有效...但我不希望通过键入它并在字符串上进行替换来构建我的选择语句,我试图将它保留在同一个 Zend_Db_Select 对象中。我还尝试将Zend_Db_Expr('RANDOM()') 传递到声明中的->order() 中,但它失败了。他还发布了一个寻找答案的理论解决方案,但我不打算重写其中的函数,修改 $db->fetch() 调用。

有什么想法吗?

【问题讨论】:

【参考方案1】:

您可以快速将函数抽象为一个表——谁知道它使用的是哪个适配器:

class MyTable extends Zend_Db_Table_Abstract 
   public function randomSelect($select=null) 
     if ($select === null) $select = $this->select();
     if (!$select instanceOf Zend_Db_Select) $select = $this->select($select);
     $adapter = $this->getAdapter();
     if ($adapter instanceOf Zend_Db_Adapter_Mysqli) 
       $select->order(new Zend_Db_Expr('RAND()'));
      else if ($adapter instanceOf Zend_Db_Adapter_Dblib) 
       $select->order(new Zend_Db_Expr('NEWID()'));
      else  
       throw new Exception('Unknown adapter in MyTable');
     
     return $select;
  


$someSelect = $table->select();
// add it to an existing select
$table->randomSelect($someSelect);

// or create one from scratch
$select = $table->randomSelect();

另外,我在某处发现了一篇丢失的文章,建议尝试以下方法:

$select->order(new Zend_Db_Expr('0*`id`+RAND()));

颠覆 MSSQL 的查询优化器并欺骗它为每一行计算一个新值。

【讨论】:

【参考方案2】:

我将创建类 My_Db_Expr_Rand 扩展 Zend_Db_Expr。根据适配器,我将返回其中一个。

【讨论】:

我喜欢它,但我想我更喜欢 gnarf 的想法。只需扩展 Table Abstract 以进行随机选择就可以了。 是的,当然。我的解决方案更复杂,来自您想要基于适配器创建 AN EXPRESSION 的东西。所以它通常可以重用于任何其他项目......但我同意表格解决方案更直接...... 在底部他还展示了 Db_Expr,您可以将其用于 MSSQL 和 MySQL,而无需对其进行修改,使其通常也可用于任何项目。 我最初认为My_Db_Expr_Rand 是解决方案,但问题是没有任何底层代码在组装查询时将当前使用的适配器传递给Zend_Db_Expr。想了想,决定表是最接近适配器的连接点。 啊。我的错,我没有检查适配器是否传递给表达式。很抱歉。

以上是关于Zend_Db_Select 随机排序,兼容 mssql / mysql的主要内容,如果未能解决你的问题,请参考以下文章

快速排序算法详解

09:明明的随机数

ms sqlServer与啥系统兼容

在 Ms. Access 中生成随机字母数字密钥

从 MS Access 检索随机记录的查询 [重复]

使用联合从 MS Access 表中选择随机记录 [重复]