Kohana: как заключить запрос в квадратные скобки?

#php #kohana

#php #kohana

Вопрос:

Мне нужно создать запрос типа (я использую PostgreSQL):

 (SELECT * FROM t1 WHERE a>b ORDER BY a DESC)  
UNION ALL  
(SELECT * FROM t1 WHERE a<b ORDER BY a DESC)  
  

Итак, я пытаюсь использовать конструктор запросов

 $query1 = DB::select('*')  
->from('t1')->where('a', '>', 'b')->order_by('a', 'desc');    

$query2 = DB::select('*')  
->from('t1')->where('a', '<', 'b')->order_by('a', 'desc');    

$result = $query1->union($query2, TRUE);  
  

Но в результате у меня есть sql-запрос, где выбирается без скобок. Вот так:

 SELECT * FROM t1 WHERE a>b ORDER BY a DESC  
UNION ALL  
SELECT * FROM t1 WHERE a<b ORDER BY a DESC  
  

И получите синтаксическую ошибку SQL… Извините за мой английский

Ответ №1:

Почему бы и нет SELECT * FROM t1 WHERE a != b ORDER BY a DESC ?

Редактировать
Для более сложного запроса, когда вам действительно нужно два или более ПОРЯДКА, я вижу только это решение:

 $query1 = DB::select()
        ->from('t1')
        ->where('a', '>', 'b')
        ->order_by('a', 'DESC')
        ->__toString();


$query2 = DB::select()
        ->from('t1')
        ->where('a', '<', 'b')
        ->order_by('a', 'DESC')
        ->__toString();

$query3 = '(' . $query1 . ') UNION ALL (' . $query2 . ')';
$result = DB::query(Database::SELECT, $query3)->execute();
  

Комментарии:

1. У меня более сложный запрос. Здесь я описываю проблему. И я хочу найти проблему, как заключить мой запрос в скобки.

2. В общем, я должен отобразить список голосов. Сначала те, за которые пользователь не проголосовал, и после всех оставшихся голосов упорядочиваются по дате

3. Краткое примечание: вам не нужно вызывать __toString() ; это делается автоматически, когда вы объединяете запросы в $query3

4. да, это работает для меня! Спасибо. Но я изменил Database_Query_Builder_Select-> compile и добавил в них скобки. Это тоже работает.

Ответ №2:

Другой способ решить эту проблему — изменить class Database_Query_Builder_Select . Таким образом, создайте запрос объединения со скобками, например: (select_1) union (select_2) union (select_n) . И вы можете использовать ORDER BY and LIMIT в каждом SELECT операторе

1) Создайте папку application/classes/database/query/builder/
2) Создайте файл select.php
3) Вставьте в созданный файл этот код:

 <?php defined('SYSPATH') or die('No direct script access.');

class Database_Query_Builder_Select extends Kohana_Database_Query_Builder_Select {

protected $_union_limit = NULL;

/**
 * Insert LIMIT statement after all unions
 * 
 * @param integer $number
 */
public function union_limit($number)
{
    $this->_union_limit = (int) $number;

    return $this;
}

/**
 * Compile the SQL query and return it.
 *
 * @param   object  Database instance
 * @return  string
 */
public function compile(Database $db)
{
    // Callback to quote columns
    $quote_column = array($db, 'quote_column');

    // Callback to quote tables
    $quote_table = array($db, 'quote_table');

    // Start a selection query
    $query = 'SELECT ';
    if ( ! empty($this->_union)) $query = DB::expr('(SELECT ');

    if ($this->_distinct === TRUE)
    {
        // Select only unique results
        $query .= 'DISTINCT ';
    }

    if (empty($this->_select))
    {
        // Select all columns
        $query .= '*';
    }
    else
    {
        // Select all columns
        $query .= implode(', ', array_unique(array_map($quote_column, $this->_select)));
    }

    if ( ! empty($this->_from))
    {
        // Set tables to select from
        $query .= ' FROM '.implode(', ', array_unique(array_map($quote_table, $this->_from)));
    }

    if ( ! empty($this->_join))
    {
        // Add tables to join
        $query .= ' '.$this->_compile_join($db, $this->_join);
    }

    if ( ! empty($this->_where))
    {
        // Add selection conditions
        $query .= ' WHERE '.$this->_compile_conditions($db, $this->_where);
    }

    if ( ! empty($this->_group_by))
    {
        // Add sorting
        $query .= ' GROUP BY '.implode(', ', array_map($quote_column, $this->_group_by));
    }

    if ( ! empty($this->_having))
    {
        // Add filtering conditions
        $query .= ' HAVING '.$this->_compile_conditions($db, $this->_having);
    }

    if ( ! empty($this->_order_by))
    {
        // Add sorting
        $query .= ' '.$this->_compile_order_by($db, $this->_order_by);
    }

    if ($this->_limit !== NULL)
    {
        // Add limiting
        $query .= ' LIMIT '.$this->_limit;
    }

    if ($this->_offset !== NULL)
    {
        // Add offsets
        $query .= ' OFFSET '.$this->_offset;
    }

    if ( ! empty($this->_union))
    {
        $iteration = 1;
        foreach ($this->_union as $u) {
            if ($iteration == 1) $query .= ')';
            $query .= ' UNION ';
            if ($u['all'] === TRUE)
            {
                $query .= 'ALL ';
            }
            $query .= '('.$u['select']->compile($db).')';

            $iteration  ;
        }
    }

    if ( ! empty($this->_union_limit))
    {
        $query .= ' LIMIT '.$this->_union_limit;
    }
    $this->_sql = $query;

    return $query;
}
  

}