2010-06-03 25 views
3

所以我有我想通過Zend框架Zend_Db的工會():Zend_Db_Table_Abstract VS Zend_Db_Table類:: getDefaultAdapter()

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我一個簡單的方法來構建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() 

- EDIT 2 -

所以我增加了第三步和合並兩個工會的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')) 

下一步是將這個聯合子句集成到主查詢中,我已經使用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); 

但似乎當「$工會」變量轉換成它以某種方式得到縮短一個字符串,這意味着我的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 

任何想法?

回答

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') 
)); 
+0

Zend的方式或不方式IMO。第一個想法是可行的,但我認爲從$ db引用中選擇的子聯合的選擇與$ this創建的不同(在模型層中)。 – emeraldjava 2010-06-04 08:15:25

+0

我遇到了我的代碼中的情況,我無法找到一種方法來執行查詢「Zend方式」:http://stackoverflow.com/questions/2596127/zend-database-adapter-complex-mysql-查詢 – Sonny 2010-06-04 14:38:35

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;  
+0

請解釋你的解決方案。 – 2012-12-10 19:33:56