问题
I'm porting an application from ZF1 to ZF2 and as part of that I have to rewrite our database mappers.
I'm struggling with this SQL statement:
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;
The underlying problem I'm trying to solve is that I need to order the results of the sub query before running GROUP_CONCAT
and I need it to work for both MySQL and Sqlite. In MySQL I could simply specify the order within the GROUP_CONCAT
function, but this is not possible with Sqlite so I need the sub query for it to be compatible with both MySQL and Sqlite.
In ZF1 I could do:
$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');
However, using a sub query in the from clause doesn't seem possible with ZF2. Is there some work around for this?
回答1:
EDIT: Actually, I now see that my query was flawed. It won't work as expected with MySQL, which means I still have to write specialized queries. See GROUP_CONCAT change GROUP BY order
After going through the code of Zend\Db\Sql\Select
I found these lines:
if ($table instanceof Select) {
$table = '(' . $this->processSubselect($table, $platform, $driver, $parameterContainer) . ')';
} else {
$table = $platform->quoteIdentifier($table);
}
So the answer is actually quite simple, all I had to do was to provide a Zend\Db\Sql\Select
object to from()
, without wrapping it in a Zend\Db\Sql\Expression
like I used to with ZF1.
Code example:
$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();
来源:https://stackoverflow.com/questions/25606544/zend-db-select-from-subquery