2013-01-20 125 views
6

嘗試使用Zend\Db\Sql\Select獲取嵌套選擇,在文檔或谷歌中根本看不到任何內容。使用ZF2嵌套選擇

想要做這樣的事情:

SELECT 
    table1.*, 
    (SELECT x,y,z FROM table2 WHERE table2.a = table1.a) as b 
FROM table1 

沒有嵌套查詢,這將是這個樣子:

$select = new Zend\Db\Sql\Select; 
$select 
->columns(array(
    '*' 
)) 
->from('table1') 

ZF1看了有關創建子查詢項目,然後將其添加爲表達式在列表中,但在ZF2中,它抱怨表達式需要是一個字符串。

編輯:嵌套選擇需要作爲列,因爲當在同一列名稱上使用GROUP BY時,我最終得到的是相乘的行。這是正確的查詢我試圖進入Zend\Db\Sql\Select

SELECT 
    users.id, 
    (SELECT count(explorations.id) FROM explorations WHERE user_id = users.id) as total_explorations, 
    count(villages.id) 
FROM 
    users 
INNER JOIN 
    villages 
     on (villages.user_id = users.id) 
GROUP BY 
    users.id 

回答

4

我建議你重組你的SQL查詢。我不確定你正在使用哪個數據庫,但是如果你使用MySQL,COUNT函數可以使用DISTINCT關鍵字。這樣你就不會計算重複的ID。我已經將SQL查詢調整爲我將要使用的內容,這樣就消除了對內部選擇的需要。

SELECT 
    users.id, 
    COUNT(DISTINCT explorations.id) AS total_explorations, 
    COUNT(DISTINCT villages.id) AS total_villages 
FROM users 
    INNER JOIN villages ON villages.user_id = users.id 
    INNER JOIN explorations ON explorations.user_id = users.id 
GROUP BY users.id 

我還沒有運行這個查詢,但我相信它應該工作,並給你你想要的結果。希望我不會誤解你的情況。下面是等效的Zend Framework 2選擇。

$select = $sql->select('users'); 
$select->columns(array('id')); 
$select->join('villages', 
       'villages.user_id = users.id', 
       array(
        'total_villages' => new Expression("COUNT(DISTINCT villages.id)") 
       ) 
); 
$select->join('explorations', 
       'explorations.user_id = users.id', 
       array(
        'total_explorations' => new Expression("COUNT(DISTINCT explorations.id)") 
       ) 
); 
0

我希望我正確地得到您的問題...

還沒升級自己ZF2但是這是你的方式一個可以在ZF1中創建嵌套的Select語句(如果使用MVC體系結構的話)(也可以在ZF2中使用它)。

$table1 = new table1(); 
    $table1->select()->from('table1',array('*', 
     'b' => '(SELECT x,y,z FROM table2 WHERE table2.a = table1.a)', 
    )); 

更新:

回來給你對此有何評論後意識到,我寫的代碼將無法正常工作,你將無法選擇從另一個多列表成一列(即b中的x,y,z)。

但是,它會工作,如果你必須執行一些agg。功能在另一個表上,它給出了一列。例如

$table1 = new table1(); 
    $table1->select()->from('table1',array('*', 
     'b' => '(count (*) FROM table2 WHERE table2.a = table1.a)', 
    )); 

所以這將工作。 通過這種方式,您可以獲得一些在其上執行某些功能的列。 其他表格(表格2)中的其他列可以使用連接。

+0

這是目前我回避的事情,因爲我無法做到這一點。剛剛寫出了SQL,如你所說,但後來一半是抽象的,另一半是原始的:D正在考慮ZF2只是允許它在列部分 –

0

您所描述的內容定義爲JOIN。有一些不同的連接方案,我不會介紹它們之間的差異,但最常見的是INNER JOIN或LEFT JOIN。

而這的確給ZF2-Documentation of Zend\Db\Sql#Join

內找到查詢應該是這樣的:

Select 
    t1.*, 
    t2.field1, 
    t2.field2, 
    t2.field3 
FROM 
    tablename1 t1, 
    tablename2 t2 
WHERE 
    t1.field = t2.field 

綜觀ZF2-Documentation of Zend\Db\Sql#Join的文檔,我認爲的選擇是這樣的:

$select = new \Zend\Db\Sql\Select(); 

$select->columns(array(
    'id', 
    'title', 
    // List ALL Columns from TABLE 1 - * is bad/slow! 
), true)->from(array(
    't1' => 'tablename1' 
))->join(
    'tablename2', 
    'id = t1.id', 
    array(
     'username', 
     'email', 
     // List ALL Columns from TABLE 2 u want to select 
    ), 
    $select::JOIN_INNER 
) 

另外我認爲:如果你不使用columns(),你會爲SELECT *,但爲了你自己的利益,開始編寫好的查詢;)更多地控制你的代碼!

不能保證這段代碼能夠正常工作,因爲我自己並沒有使用Zend \ Db,但在正確的點上使用文檔應該可以讓你繼續運行。

+0

嗯,我使用其他連接以及不能做另一個,因爲它我使用多個count()和sum()來倍增行。我是由一個特定的字段分組,但是這也被用在了連接表中,所以我認爲除了嵌套選擇以外,沒有其他解決辦法。 –

6

Ralph Schindler擁有一個他在Zend \ Db中專門實現的不同DB模式的存儲庫。這裏有一個子查詢:https://github.com/ralphschindler/Zend_Db-Examples/blob/master/example-20.php

內容是這樣的:

<?php 

/** @var $adapter Zend\Db\Adapter\Adapter */ 
$adapter = include ((file_exists('bootstrap.php')) ? 'bootstrap.php' : 'bootstrap.dist.php'); 
refresh_data($adapter); 

use Zend\Db\Sql; 
use Zend\Db\ResultSet\ResultSet; 

$sql = new Sql\Sql($adapter); 

$subselect = $sql->select(); 
$subselect->from('artist') 
    ->columns(array('name')) 
    ->join('album', 'artist.id = album.artist_id', array()) 
    ->where->greaterThan('release_date', '2005-01-01'); 


$select = $sql->select(); 
$select->from('artist') 
    ->order(array('name' => Sql\Select::ORDER_ASCENDING)) 
    ->where 
     ->like('name', 'L%') 
     ->AND->in('name', $subselect); 

$statement = $sql->prepareStatementForSqlObject($select); 

$result = $statement->execute(); 

$rows = array_values(iterator_to_array($result)); 

assert_example_works(
    count($rows) == 2 
    && $rows[0]['name'] == 'Lady Gaga' 
    && $rows[1]['name'] == 'Linkin Park' 
); 

基本上,你可以使用一個選擇作爲另一個選擇的謂詞的值。

+0

是否有可能做一個SubSelect作爲額外的列,雖然沒有進行其他數據庫調用?如果我有超過1個計數,我會得到相乘的行,所以有一個子選擇來解決這個問題。我在我的原始問題中發佈了一個示例SQL來展示我的意思:) –