Darryl Hein
Darryl Hein

Reputation: 145027

How do I build a UNION query with ORDER BY and GROUP BY in Kohana's query builder?

I'm trying to build a UNION query using Kohana's query builder. Everything works fine until I add a GROUP BY or ORDER BY clause.

Here is the code I'm using (simplified):

$query1 = DB::select('p.name')
    ->from(array('person', 'p'))
    ->where('p.organization', 'LIKE', 'foo%')
    ->limit(10);

$names = DB::select('sh.name')
    ->union($query1, FALSE)
    ->from(array('stakeholder', 'sh'))
    ->where('sh.organization', 'LIKE', 'foo%')
    ->group_by('name')
    ->order_by('name')
    ->limit(10)
    ->execute()
    ->as_array();

Instead of adding the GROUP BY and ORDER BY at the end of the entire query, it's adding it immediately after the second query.

This is the SQL this generates:

 SELECT sh.name FROM stakeholder AS sh WHERE sh.organization LIKE 'foo%' 
 GROUP BY name ORDER BY name LIMIT 10
 UNION
 SELECT p.name from person AS p WHERE p.organization LIKE 'foo%' LIMIT 10;

What I want is:

 SELECT sh.name FROM stakeholder AS sh WHERE sh.organization LIKE 'foo%'
 UNION
 SELECT p.name from person AS p WHERE p.organization LIKE 'foo%'
 GROUP BY name ORDER BY name LIMIT 10;

Upvotes: 5

Views: 4093

Answers (3)

helpse
helpse

Reputation: 1548

You can also extend Kohana_ORM using ORM's db_pending:

class ORM extends Kohana_ORM {
    public function union($table, $all = TRUE)
    {
        // Add pending database call which is executed after query type is determined
        $this->_db_pending[] = array(
            'name' => 'union',
            'args' => array($table, $all),
        );

        return $this;
    }
}

Usage:

ORM::factory('MyModel')
    ->union(DB::select(DB::expr("'RP' id, 'Pasantías' name, 'Pasantías' short_name, 'R' parent_id, null data")))
    ->union(DB::select(DB::expr("'RC' id, 'Capacitación' name, 'Capacitación' short_name, 'R' parent_id, null data")))
    ->join(['catalogo', 'p'])->on('catalogo.parent_id', '=', 'p.id')
    ->where('p.parent_id', 'is', NULL)
    ->where('catalogo.id', 'not in', ['RV', 'RPA', 'RPT']);

Upvotes: 1

Petr
Petr

Reputation: 111

That answer from 2011 isn't working in Kohana 3.3.

But I found this module: https://github.com/Invision70/kohana-orm-union

Upvotes: 0

random
random

Reputation: 9955

The clauses here are applied from the first query set up in the union() method, so just reverse where you're putting them:

$query1 = DB::select('p.name')
              ->from(array('person', 'p'))
              ->where('p.organization', 'LIKE', 'foo%')
              ->group_by('name')
              ->order_by('name')
              ->limit(10);

$names = DB::select('sh.name')
              ->union($query1, FALSE)
              ->from(array('stakeholder', 'sh'))
              ->where('sh.organization', 'LIKE', 'foo%')
              ->execute()
              ->as_array();

You can also remove that superfluous ->limit(10) from $names since it will be ignored and superseded by the one in $query1.

Upvotes: 6

Related Questions