32

如何使用 PHP CodeIgniter 框架的活动记录查询格式进行 UNION 查询?

4

10 回答 10

38

CodeIgniter 的 ActiveRecord 不支持 UNION,因此您只需编写查询并使用 ActiveRecord 的查询方法。

$this->db->query('SELECT column_name(s) FROM table_name1 UNION SELECT column_name(s) FROM table_name2');
于 2010-01-11T20:39:29.380 回答
29

通过使用 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();
于 2011-12-12T11:39:51.300 回答
25

这是我曾经使用过的一种快速而肮脏的方法

// 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);

不是我最好的作品,但它解决了我的问题。

注意:我不需要订购结果。

于 2012-12-17T02:16:15.640 回答
8

您可以使用以下方法获取模型中的 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 变量中,而无需实际执行。

你很久以前就问过这个问题,所以也许你已经得到了答案。如果没有,这个过程可能会奏效。

于 2011-06-27T15:28:15.797 回答
3

通过修改 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`)
于 2013-02-02T03:02:02.377 回答
2

我找到了这个库,它非常适合我以 ActiveRecord 样式添加 UNION:

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

但是我必须首先get_compiled_select()从 CodeIgniter 的 dev 分支获取方法(可在此处获得: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 的开发版本,因为这是一个生产应用程序。)

于 2013-01-11T00:58:41.243 回答
2

这是我正在使用的解决方案:

$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);
于 2017-01-26T22:26:11.813 回答
1

试试这个

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();
}
于 2015-07-13T07:37:27.427 回答
0

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");
于 2018-09-27T10:00:48.290 回答
-1

这是我创建的解决方案:

$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);
于 2011-03-24T21:07:34.903 回答