所以我有我想通过 zend 框架调用的原始 SQL
select t.type, t.tid,t.tname,t.cid,t.cname, ls.*
from
(
select t.type, t.id as tid, t.name as tname, c.id as cid, c.name as cname from team t
join company c on t.parent=c.id and t.type='C' and c.sector=20 and t.status='ACTIVE'
union
select t.type, t.id as tid,t.name as tname, null as cid, null as cname from team t
join sector s on t.parent=s.id and t.type='S'and s.id=20 and t.status='ACTIVE'
) t
LEFT JOIN leaguesummary ls ON ls.leagueparticipantid=t.tid AND ls.leaguetype='T'
WHERE ls.leagueid = 5
ORDER BY ls.leaguedivision asc, ls.leagueposition asc LIMIT 10;
我的模型类扩展了 Zend_Db_Table 我有一个简单的方法来构建 SQL 并查询它
class Model_DbTable_LeagueSummary extends Zend_Db_Table_Abstract {
....
public function getTeamLeagueSummayBySector($sectorid,$limit=10)
{
$select = $this->select()
->setIntegrityCheck(false)
->from(array('team'=>'team'),array('type','id','name'))
->join(array('company'=>'company'),'team.parent=company.id',array())
->where('team.type="C"')
->where('team.status="ACTIVE"')
->where('company.sector=?',$sectorid);
$select2 = $this->select()
->setIntegrityCheck(false)
->from(array('team'=>'team'),array('type','id','name'))
->join(array('sector'=>'sector'),'team.parent=sector.id',array())
->where('team.type="S"')
->where('team.status="ACTIVE"')
->where('sector.id=?',$sectorid);
// manually creating the SQL string and calling Zend_Db_Table::getDefaultAdapter() directly
$STRING = sprintf("select x.*,ls.* from ( %s union %s ) x
LEFT JOIN leaguesummary ls ON ls.leagueparticipantid=x.id AND ls.leaguetype='T'
WHERE ls.leagueid = 5
ORDER BY ls.leaguedivision asc, ls.leagueposition asc LIMIT 10;",$select,$select2);
$db = Zend_Db_Table::getDefaultAdapter();
$stmt = $db->query($STRING);
$stmt->setFetchMode(Zend_Db::FETCH_OBJ);
$result = $stmt->fetchAll();
return $result;
}
此查询有效,但不喜欢该解决方案并希望重构代码以更正确地使用 Zend_DB 方法。我已经走到这一步了
$sql = $this->select()
->setIntegrityCheck(false)
->from(array('X'=>'X'))
->union(array($select,$select2))
->joinLeft(array('leaguesummary'=>'leaguesummary'),'leaguesummary.leagueparticipantid=X.id')
->where('leaguesummary.leaguetype="T"')
->where("leaguesummary.leagueid = ?",5)
->order("leaguesummary.leaguedivision asc")
->order("leaguesummary.leagueposition asc")
->limit($limit);
return $db->fetchAll($sql);
但是我得到了这个异常(exception)。工会声明有什么问题?
Message: Invalid use of table with UNION
Stack trace:
#0 /home/assure/bhaa/zend/trunk/library/Zend/Db/Select.php(357): Zend_Db_Select->_join('left join', Array, 'leaguesummary.l...', '*', NULL)
#1 /home/assure/bhaa/zend/trunk/application/models/DbTable/LeagueSummary.php(175): Zend_Db_Select->joinLeft(Array, 'leaguesummary.l...')
#2 /home/assure/bhaa/zend/trunk/application/controllers/HousesController.php(110): Model_DbTable_LeagueSummary->getTeamLeagueSummayBySector('20')
#3 /home/assure/bhaa/zend/trunk/library/Zend/Controller/Action.php(513): HousesController->sectorAction()
#4 /home/assure/bhaa/zend/trunk/library/Zend/Controller/Dispatcher/Standard.php(289): Zend_Controller_Action->dispatch('sectorAction')
#5 /home/assure/bhaa/zend/trunk/library/Zend/Controller/Front.php(954): Zend_Controller_Dispatcher_Standard->dispatch(Object(Zend_Controller_Request_Http), Object(Zend_Controller_Response_Http))
#6 /home/assure/bhaa/zend/trunk/library/Zend/Application/Bootstrap/Bootstrap.php(97): Zend_Controller_Front->dispatch()
#7 /home/assure/bhaa/zend/trunk/library/Zend/Application.php(366): Zend_Application_Bootstrap_Bootstrap->run()
-- 编辑 2 --
所以我添加了第三步,像这样合并两个 union sql 语句
$union = $this->getDefaultAdapter()->select()->union(array($select,$select2));
$logger->info(sprintf(' (%s) ',$union));
这给了我有效的 SQL
2010-06-04T15:11:55+00:00 INFO (6): (SELECT `team`.`type`, `team`.`id`, `team`.`name` FROM `team` INNER JOIN `company` ON team.parent=company.id WHERE (team.type="C") AND (team.status="ACTIVE") AND (company.sector='20') UNION SELECT `team`.`type`, `team`.`id`, `team`.`name` FROM `team` INNER JOIN `sector` ON team.parent=sector.id WHERE (team.type="S") AND (team.status="ACTIVE") AND (sector.id='20'))
下一步是将这个 union 子句集成到主查询中,我像这样使用 from() 子句
->from(array('X'=> '('.$union.')' ) )
->joinLeft(array('leaguesummary'=>'leaguesummary'),'leaguesummary.leagueparticipantid=X.id')
->where('leaguesummary.leaguetype="T"')
->where("leaguesummary.leagueid = ?",5)
->order("leaguesummary.leaguedivision asc")
->order("leaguesummary.leagueposition asc")
->limit($limit);
$logger->info(sprintf('%s',$sql));
return $this->getDefaultAdapter()->fetchAll($sql);
但似乎当“$union”变量转换为字符串时,它以某种方式缩短了,这意味着我的 SQL 无效
SELECT `X`.*, `leaguesummary`.* FROM `(SELECT ``team```.```type``, ``team``` AS `X` LEFT JOIN `leaguesummary` ON leaguesummary.leagueparticipantid=X.id WHERE (leaguesummary.leaguetype="T") AND (leaguesummary.leagueid = 5) ORDER BY `leaguesummary`.`leaguedivision` asc, `leaguesummary`.`leagueposition` asc LIMIT 10
有什么想法吗?
最佳答案
对于像您这样“复杂”的查询,您可能不想以“Zend”方式进行查询。您可以将 query() 函数与原始 SQL 一起使用
$rows = $this->getAdapter()->query("
select t.type, t.tid,t.tname,t.cid,t.cname, ls.*
from
(
select t.type, t.id as tid, t.name as tname, c.id as cid, c.name as cname from team t
join company c on t.parent=c.id and t.type='C' and c.sector=20 and t.status='ACTIVE'
union
select t.type, t.id as tid,t.name as tname, null as cid, null as cname from team t
join sector s on t.parent=s.id and t.type='S'and s.id=20 and t.status='ACTIVE'
) t
LEFT JOIN leaguesummary ls ON ls.leagueparticipantid=t.tid AND ls.leaguetype='T'
WHERE ls.leagueid = 5
ORDER BY ls.leaguedivision asc, ls.leagueposition asc LIMIT 10;
");
This bug报告显示了 union() 函数的正确用法:
$selectA = $db->select()
->from(array('u' => 'user'), 'name')
->where('u.id >= 5');
$selectB = $db->select()
->from(array('u' => 'user'), 'name')
->where('u.id < 5');
$select = $db->select()
->union(array($selectA, $selectB));
或者:
$select = $db->select()
->union(array(
$db->select()
->from(array('u' => 'user'), 'name')
->where('u.id >= 5'),
$db->select()
->from(array('u' => 'user'), 'name')
->where('u.id < 5')
));
关于php - Zend_DB union() :Zend_Db_Table_Abstract 与 Zend_Db_Table::getDefaultAdapter(),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2967763/
在railstutorial中,作者为什么选择使用这个(代码list10.25):http://ruby.railstutorial.org/chapters/updating-showing-and-deleting-usersnamespace:dbdodesc"Filldatabasewithsampledata"task:populate=>:environmentdoRake::Task['db:reset'].invokeUser.create!(:name=>"ExampleUser",:email=>"example@railstutorial.org",:passwo
我是RoR的新手,我正在学习MichaelHartl的教程(所以请随意更正我在您认为合适的地方使用的术语)。在第2章中,我通过运行以下行创建了一个Users表:$railsgeneratescaffoldUsername:stringemail:string$bundleexecrakedb:migrate然后,我运行了下面的代码来尝试创建一个Microposts表(但是,我拼错了没有“r”的Micropost!)...$railsgeneratescaffoldMiropostcontent:stringuser_id:integer$bundleexecrakedb:migrate
我在新的Rails应用程序(3.2.3)中运行迁移时遇到了问题。我们正在使用postrgres9.1.3和-pg(0.13.2)-当我运行rakedb:create,然后运行rakedb:migrate,我得到->1.9.3-p194(master)rakedb:migrate--trace**Invokedb:migrate(first_time)**Invokeenvironment(first_time)**Executeenvironmentrakeaborted!PG::Error:ERROR:relation"roles"doesnotexistLINE4:WHEREa
为什么rakedb:migrate运行Executedb:schema:dump我的输出全都搞砸了(显示SQL)。看起来像这样:ActiveRecord::SchemaMigrationLoad(0.5ms)SELECT"schema_migrations".*FROM"schema_migrations"(3.7ms)SELECTt2.oid::regclass::textASto_table,a1.attnameAScolumn,a2.attnameASprimary_key,c.connameASname,c.confupdtypeASon_update,c.confdeltyp
我正在寻找一个清晰的Rails4示例,说明如何根据通过另一个表关联的数据过滤记录。假设我有一个用户模型和一个评论模型。一个用户has_many评论,一个Commentbelongs_to一个用户。评论在其表中也有一个score列。classUserUsers|id|name|email||-----|---------|---------------------||1|"Alice"|"alice@example.com"||2|"Bob"|"bob@example.com"||...|classComment我如何获得所有对内容“k”发表评论且分数>0的用户?请注意,我要返回的是用户
我想在请求期间动态更改ActiveRecord模型类的表名。例如,有许多具有相似结构(列)的表:mydb:sample_data_12222sample_data_12223sample_data_12224sample_data_12225...所以,我想做的是..._1。定义基本模型类,如:classSampleData_2。在请求期间更改目标表,例如:defaction_methodSampleData.set_table_name"sample_data_#{params[:id]}"@rows=SampleData.all如果在非线程环境(如Passenger/mod_rai
我在prawn中创建了一个表,并希望通过whih传递:position选项,这在手册中也有记录,但它引发了Method_missing错误。好像这个参数不存在了。我怎样才能让Prawn居中? 最佳答案 我遇到了同样的错误。从Github上的master安装解决了这个问题。#Gemfilegem'prawn',git:'https://github.com/prawnpdf/prawn.git'IssuethreadonGithub 关于ruby-on-rails-如何在Prawn中居中t
我正在尝试使用RubygemRestClient为我的一个FusionTables更新样式。这是我的代码:require'rest_client'tableId=''styleId=''key=''table_url="https://www.googleapis.com/fusiontables/v1/tables/#{tableId}/styles/#{styleId}?key=#{key}"update='{"polygonOptions":{"strokeColor":"#ffffff"}}'token='STRINGCONTAININGAUTHORIZATIONTOKEN'R
我在Rails3中进行数据库迁移时遇到异常。undefinedmethod`visitor'for#编辑请查看解决方案here.在我的项目中没有出现字符串visitor所以我很困惑。这是完整的转储:$rakedb:migrate--trace**Invokedb:migrate(first_time)**Invokeenvironment(first_time)**Executeenvironment**Invokedb:load_config(first_time)**Invokerails_env(first_time)**Executerails_env**Executedb:l
好的,所以我有一个Rails应用程序,我试图在postgres数据库上运行迁移,我通常使用mysql,一切都很好,但是当我运行命令时,我得到了这个rakedb:migrate(in/Users/tamer/Sites/my_app)/Users/tamer/.rvm/gems/ruby-1.9.2-p290@my_app/gems/activerecord-3.0.3/lib/active_record/connection_adapters/postgresql_adapter.rb:487:[BUG]Segmentationfaultruby1.9.2p290(2011-07-09