Love Fuel?    Donate

FuelPHP Forums

Ask your question about FuelPHP in the appropriate forum, or help others by answering their questions.
Any plans to support UNION in the Query Builder?
  • Hello.
    Are there any reasons not to support UNION in the Query Builder?

    To use UNION in my query, currently I use the Query Builder to build two SELECT queries separately, then compile() each of them, and then combine them to one SQL string with ' UNION ' and ORDER BY clause string (which is built manually). The resulted SQL string is passed to DB::query($sql_string, DB::SELECT). 
    Though it works fine, I simply want to know why it cannot be done without the manual SQL string concatenating.

    The documentation says "The query method returns a new Database_Query_Builder object". Actually it returns a Database_Query object, which has no order_by() method, so I have to build an ORDER BY clause string and concatenate it manually aside from the manual ' UNION ' concatenating.

    Kohana and Laravel seem to have support for UNION in their Query Builders.
  • The query builder is a component that came from the Kohana framework, over three years ago, and little has changed since then. The underlying database layer is not very good, so we decided do dump it an rewrite if for Fuel v2.

    Which is why not a lot of effort is put into the current code anymore.

    From the looks of it, it should be quite easy to port. If you want to have a stab at it, and send in a PR? This is the commit that added it: https://github.com/kohana/database/commit/2b4c6579e51e74c962b91e0db9bdcd48a33f5860
  • Thanks for your answer. I'll send an PR.

    But I found one thing that doesn't suit me in the Kohana's implementation.
    Can I get your opinion?

    $query1->union($query2)->order_by($column, $direction);
    The above code doesn't work, because in the resulted SQL the ORDER BY clause is appended to just after the SQL from $query1.
    The resulted SQL is like below.
    "{$sql_from_query1} {$order_by} UNION {$sql_from_query2}"
    This gets an error in MySQL.
    > Incorrect usage of UNION and ORDER BY

    $query1->union($query2->order_by($column, $direction));
    This code works. The resulted SQL becomes like below.
    "{$sql_from_query1} UNION {$sql_from_query2} {$order_by}"
    This sorts the entire result of the UNION.
    But I think it's not intuitive, though the result is what I expected in the previous code.

    I have three choices.
    1. Leave it as it is and send PR. Kohana is justice.
    2. Put the UNION combining code before the code appending the ORDER BY and LIMIT clauses in the compile() method, so $query1->union($query2)->order_by($column, $direction) works as expected.

    From I read the PR above, each three cases below has a different behavior.
    $query1->union($query2)->order_by(...);
    $query1->order_by(...)->union($query2);
    $query1->union($query2->order_by(...));
    Call to order_by() after union() sorts the entire UNION.
    Call to order_by() before union() sorts only the calling query, and each queries are parenthesized separately.

    Which is the better solution?
  • Ideally you should run this by FrenkyNet, he deals with Fuel's DB.

    But I would say to treat this the same way subqueries are treated, in which case this becomes a non-issue.

    $q1 = DB::select()->...;
    $q2 = DB::select()->...->union($q1)->...;

    This way both are different queries, so you either apply order_by() on one, or on the other, there will never be a mix-up.
  • Thank you!
    I agree. There should be a way to apply order_by() on each query. It might look like subqueries.
    The remaining problem is how to apply order_by() on entire UNION.

    I'm leaning toward the 3rd choice, the idea of the PR to Laravel.
    Yes, "order_by() behaves differently depending on whether or not an union() has been called before" is a bit wired, not very comfortable.
    But "$q1->union($q2)->order_by($foo) results 'q1 ORDER BY foo UNION q2'" is more wired.

    I'll go this way if FrenkyNet (or anyone) has no objections to it.
  • Oops!
    s/wired/weird/g
    nothing is wired. somehow I'm wired.

Howdy, Stranger!

It looks like you're new here. If you want to get involved, click one of these buttons!

In this Discussion