Zend\Db:从子查询中选择

Lar*_*röm 0 mysql sqlite zend-db zend-framework2

我正在将应用程序从ZF1移植到ZF2,作为其中的一部分,我必须重写我们的数据库映射器.

我正在努力解决这个SQL语句:

SELECT full_name, GROUP_CONCAT(value)
FROM (
   SELECT full_name, value
   FROM my_table
   ORDER BY id DESC
   ) as subtable
GROUP BY full_name
ORDER BY full_name DESC;
Run Code Online (Sandbox Code Playgroud)

我试图解决的根本问题是我需要在运行之前订购子查询的结果,GROUP_CONCAT我需要它适用于MySQL和Sqlite.在MySQL中,我可以简单地指定GROUP_CONCAT函数内的顺序,但这对于Sqlite是不可能的,所以我需要子查询才能兼容MySQL和Sqlite.

在ZF1中,我可以这样做:

$fromSql = $db->select()
              ->from('my_table', array('full_name', 'value'))
              ->order('id DESC');

$sql = $db->select()
          ->from(array(
                'subtable' => new Zend_Db_Expr('(' . $fromSql . ')')
            ), array(
                'full_name' => 'full_name',
                'value' => new Zend_Db_Expr('GROUP_CONCAT(subtable.value)'),
            )
          )
          ->group('full_name')
          ->order('full_name DESC');
Run Code Online (Sandbox Code Playgroud)

但是,使用ZF2似乎不可能在from子句中使用子查询.有没有解决这个问题?

Lar*_*röm 6

编辑:实际上,我现在看到我的查询有缺陷.它不会像MySQL预期的那样工作,这意味着我仍然需要编写专门的查询.请参阅GROUP_CONCAT更改GROUP BY顺序


经过Zend\Db\Sql\Select我的代码后发现这些行:

if ($table instanceof Select) {
    $table = '(' . $this->processSubselect($table, $platform, $driver, $parameterContainer) . ')';
} else {
    $table = $platform->quoteIdentifier($table);
}
Run Code Online (Sandbox Code Playgroud)

所以答案实际上非常简单,我所要做的就是提供一个Zend\Db\Sql\Select对象from(),而不是Zend\Db\Sql\Expression像以前那样用ZF1 包装它.

代码示例:

$adapter = $this->getAdapter(); // Returns Zend\Db\Adapter\Adapter
$sql = new Zend\Db\Sql\Sql($adapter);

$from = $sql->select()
    ->from(static::$table)
    ->columns(array(
        'full_name',
        'value',
    ))
    ->order('id DESC');

$select = $sql->select()
    ->from(array(
        'subtable' => $from,
    ))
    ->columns(array(
        'full_name' => 'full_name',
        'value' => new Expression('GROUP_CONCAT(value)'),
    ))
    ->group('full_name')
    ->order('full_name DESC');

$selectString = $sql->getSqlStringForSqlObject($select);

$resultSet = $adapter->query($selectString, $adapter::QUERY_MODE_EXECUTE);

return $resultSet->toArray();
Run Code Online (Sandbox Code Playgroud)