6

试图使用嵌套选择Zend\Db\Sql\Select,但在文档或谷歌上根本看不到任何东西。

想做这样的事情:

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 考虑创建一个 subSelect 项,然后将其作为表达式添加到列列表中,但在 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

4 回答 4

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

基本上,您可以使用一个选择作为另一个选择的谓词的值。

于 2013-01-21T23:27:34.207 回答
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)")
               )
);
于 2013-04-24T04:33:20.240 回答
0

我希望我能正确解决您的问题...

仍然没有将自己升级到 ZF2,但如果您使用 MVC 架构,这是您可以在 ZF1 中创建嵌套 Select 语句的一种方式(也可以在 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)。

但是是的,如果你必须执行一些聚合,它会起作用。另一个表上的函数,它给出一列。例如

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

所以这会起作用。通过这种方式,您可以获得一些对其执行某些功能的列。您可以使用连接获得另一个表(table2)中的其余列。

于 2013-01-20T04:14:16.137 回答
0

您所描述的内容被定义为JOIN。有一些不同的连接场景,我不会介绍它们的区别,但最常见的是 INNER JOIN 或 LEFT JOIN。

这确实可以在Zend\Db\Sql#Join 的 ZF2 文档中找到

查询将如下所示:

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

查看Zend\Db\Sql#Join 的 ZF2-Documentation 的文档,我认为Select 看起来像这样:

$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,但是在正确的位置使用文档应该可以让你运行。

于 2013-01-20T09:44:02.647 回答