UNION-запрос с шаблоном активной записи codeigniter - PullRequest
28 голосов
/ 11 января 2010

Как выполнить запрос UNION с помощью формата запроса активной записи PHP CodeIgniter Framework?

Ответы [ 10 ]

32 голосов
/ 11 января 2010

CodeIgniter ActiveRecord не поддерживает UNION, поэтому вы просто пишете запрос и используете метод запроса ActiveRecord.

$this->db->query('SELECT column_name(s) FROM table_name1 UNION SELECT column_name(s) FROM table_name2');
22 голосов
/ 17 декабря 2012

Это быстрый и грязный метод, который я когда-то использовал

// Query #1

$this->db->select('title, content, date');
$this->db->from('mytable1');
$query1 = $this->db->get()->result();

// Query #2

$this->db->select('title, content, date');
$this->db->from('mytable2');
$query2 = $this->db->get()->result();

// Merge both query results

$query = array_merge($query1, $query2);

Не самая лучшая моя работа, но она решила мою проблему.

примечание: мне не нужно было заказывать результат.

19 голосов
/ 12 декабря 2011

Объединение с использованием last_query () может снизить производительность приложения. Потому что для одиночного объединения потребуется 3 запроса. т.е. для "n" объединения "n + 1" запросов. Это не сильно повлияет на объединение 1-2 запросов. Но это создаст проблему, если объединить множество запросов или таблиц с большими данными.

Эта ссылка вам очень поможет: подзапросы активной записи

Мы можем объединить активную запись с ручными запросами. Пример:

// #1 SubQueries no.1 -------------------------------------------

$this->db->select('title, content, date');
$this->db->from('mytable');
$query = $this->db->get();
$subQuery1 = $this->db->_compile_select();

$this->db->_reset_select();

// #2 SubQueries no.2 -------------------------------------------

$this->db->select('title, content, date');
$this->db->from('mytable2');
$query = $this->db->get();
$subQuery2 = $this->db->_compile_select();

$this->db->_reset_select();

// #3 Union with Simple Manual Queries --------------------------

$this->db->query("select * from ($subQuery1 UNION $subQuery2) as unionTable");

// #3 (alternative) Union with another Active Record ------------

$this->db->from("($subQuery1 UNION $subQuery2)");
$this->db->get();
8 голосов
/ 27 июня 2011

Вы можете использовать следующий метод для получения оператора SQL в модели:

$this->db->select('DISTINCT(user_id)');
$this->db->from('users_master');
$this->db->where('role_id', '1');

$subquery = $this->db->_compile_select();
$this->db->_reset_select();

Таким образом, оператор SQL будет находиться в переменной $ subquery без фактического его выполнения.

Вы задавали этот вопрос очень давно, поэтому, возможно, вы уже получили ответ. если нет, этот процесс может помочь.

3 голосов
/ 02 февраля 2013

изменяя ответ somnath huluks, я добавляю следующие переменные и функции в класс DB_Active_rec следующим образом:

class DB_Active_records extends CI_DB_Driver
{

   ....

   var $unions;

   ....

    public function union_push($table = '')
    {
        if ($table != '')
        {
            $this->_track_aliases($table);
            $this->from($table);
        }

        $sql = $this->_compile_select();

        array_push($this->unions, $sql);
        $this->_reset_select();
    }

    public function union_flush()
    {
        $this->unions = array();
    }

    public function union()
    {
        $sql = '('.implode(') union (', $this->unions).')';
        $result = $this->query($sql);
        $this->union_flush();
        return $result;
    }

    public function union_all()
    {
        $sql = '('.implode(') union all (', $this->unions).')';
        $result = $this->query($sql);
        $this->union_flush();
        return $result;
    }
}

поэтому вы можете виртуально использовать союзы без зависимостей от db_driver.

чтобы использовать union с этим методом, вы просто делаете регулярные запросы на активные записи, но вызываете union_push вместо get.

примечание: вы должны убедиться, что в ваших запросах совпадают столбцы, такие как регулярные объединения

пример:

    $this->db->select('l.tpid, l.lesson, l.lesson_type, l.content, l.file');
    $this->db->where(array('l.requirement' => 0));
    $this->db->union_push('lessons l');
    $this->db->select('l.tpid, l.lesson, l.lesson_type, l.content, l.file');
    $this->db->from('lessons l');
    $this->db->join('scores s', 'l.requirement = s.lid');
    $this->db->union_push();
    $query = $this->db->union_all();
    return $query->result_array();

будет производить:

(SELECT `l`.`tpid`, `l`.`lesson`, `l`.`lesson_type`, `l`.`content`, `l`.`file`
FROM `lessons` l
WHERE `l`.`requirement`=0)
union all 
(SELECT `l`.`tpid`, `l`.`lesson`, `l`.`lesson_type`, `l`.`content`, `l`.`file`
FROM `lessons` l
JOIN `scores` s ON `l`.`requirement`=`s`.`lid`)
2 голосов
/ 11 января 2013

Я нашел эту библиотеку, которая отлично работала для меня, чтобы добавить UNION в стиле ActiveRecord:

https://github.com/NTICompass/CodeIgniter-Subqueries

НО мне сначала нужно было извлечь метод get_compiled_select() из ветви dev CodeIgniter (доступно здесь: https://github.com/EllisLab/CodeIgniter/blob/develop/system/database/DB_query_builder.php - DB_query_builder заменит DB_active_rec). Предположительно, этот метод будет доступен в будущем выпуске CodeIgniter.

Как только я добавил этот метод в DB_active_rec.php в системе / базе данных, он работал как чудо. (Я не хотел использовать версию CodeIgniter для разработчиков, поскольку это производственное приложение.)

1 голос
/ 27 января 2017

Это решение, которое я использую:

$union_queries = array();
$tables = array('table1','table2'); //As much as you need
foreach($tables as $table){
    $this->db->select(" {$table}.row1, 
                        {$table}.row2,
                        {$table}.row3");
    $this->db->from($table);
    //I have additional join too (removed from this example)
    $this->db->where('row4',1);
    $union_queries[] = $this->db->get_compiled_select();
}
$union_query = join(' UNION ALL ',$union_queries); // I use UNION ALL
$union_query .= " ORDER BY row1 DESC LIMIT 0,10";
$query = $this->db->query($union_query);
1 голос
/ 13 июля 2015

попробуйте это

function get_merged_result($ids){                   
    $this->db->select("column");
    $this->db->distinct();
    $this->db->from("table_name");
    $this->db->where_in("id",$model_ids);
    $this->db->get(); 
    $query1 = $this->db->last_query();

    $this->db->select("column2 as column");
    $this->db->distinct();
    $this->db->from("table_name");
    $this->db->where_in("id",$model_ids);

    $this->db->get(); 
    $query2 =  $this->db->last_query();
    $query = $this->db->query($query1." UNION ".$query2);

    return $query->result();
}
0 голосов
/ 27 сентября 2018

Ответ bwisn лучше всех и будет работать, но не с хорошей производительностью, потому что он сначала выполнит подзапросы. get_compiled_select не запускает запрос; он просто компилируется для последующего запуска, так быстрее попробуйте это

$this->db->select('title, content, date');
$this->db->where('condition',value);
$query1= get_compiled_select("table1",FALSE);
$this->db->reset_query();

$this->db->select('title, content, date');
$this->db->where('condition',value);
$query2= get_compiled_select("table2",FALSE);
$this->db->reset_query();

$query = $this->db->query("$query1 UNION $query2");
0 голосов
/ 25 марта 2011

Вот решение, которое я создал:

$query1 = $this->db->get('Example_Table1');
$join1 = $this->db->last_query();
$query2 = $this->db->get('Example_Table2');
$join2 = $this->db->last_query();
$union_query = $this->db->query($join1.' UNION '.$join2.' ORDER BY column1,column2);
...