好的就是这种情况,我有一个用Zend_Framework编写的应用程序,它兼容MySQL和MSSQL作为后端。现在,ZF非常擅长解决这两种语言之间的许多SQL差异/差异,但我仍然没有想到这一点。
目标是从表中选择1个随机记录,这是一个非常简单的陈述。
这是一个选择语句,例如:
$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()')
);
它的工作原理......但我不打算通过键入它并对字符串进行替换来构建我的select语句,我试图将它保存在相同的Zend_Db_Select对象中。我也尝试将Zend_Db_Expr('RANDOM()')
传递到声明中的->order()
,但它失败了。他还发布了一个理论解决方案来找到答案,但我不打算重写这个函数,修改$ db-> fetch()调用。
有什么想法吗?
答案 0 :(得分:14)
你可以快速将函数抽象到一个表 - 谁知道它正在使用哪个适配器:
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的查询优化器并欺骗它计算每一行的新值。
答案 1 :(得分:2)
我会创建类My_Db_Expr_Rand扩展Zend_Db_Expr。基于适配器,我将返回一个或另一个。