Zend_DB union():Zend_Db_Table_Abstract与Zend_Db_Table :: getDefaultAdapter()

时间:2010-06-03 16:10:09

标签: php sql zend-framework

所以我想通过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);

但我得到了这个例外。工会声明有什么问题?

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

有什么想法吗?

2 个答案:

答案 0 :(得分:3)

对于像您这样“复杂”的查询,您可能不希望以“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')
));

答案 1 :(得分:1)

    $pmSort =   'user_lname DESC';

    $qry1=$this->select()
            ->setIntegrityCheck(false)
            ->from(array('team'=>'plg_team'),array('team_id','team_name','team_sprt_id','team_user_id'))
            ->joinInner(array('user'=>'plg_users'),'user.user_id=team_user_id',array('user_fname','user_lname','user_email'))
            ->where("team_id='$pmTeamID' and team_status=1 and user_status=1");

    $qry2=$this->select()
            ->setIntegrityCheck(false)
            ->from(array('t'=>'plg_team'),array('team_id'))
            ->joinInner(array('tp'=>'plg_team_players'),'t.team_id = tp.plyr_team_id',array('plyr_id'))
            ->joinInner(array('rlsp'=>'plg_relationships'),'rlsp.rlsp_rsty_id = 2',array('rlsp_id'))
            ->joinInner(array('user'=>'plg_users'),'user.user_id = rlsp.rlsp_relation_user_id',array('user_id','user_fname','user_lname','user_email'))
            ->where("user.user_status=1 and t.team_status=1 and tp.plyr_status=1 and t.team_id='$pmTeamID' and rlsp.rlsp_user_id = tp.plyr_user_id");        

    $select = $this->select()
            ->setIntegrityCheck(false)
            ->union(array($qry1, $qry2));
    $select1 = $this->select()
            ->setIntegrityCheck(false)
            ->from(array('T'=> $select ) )
            ->order($pmSort);

    echo $select1;      
相关问题