0

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 Answer 1

8

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();
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.