如何使用 PHP CodeIgniter 框架的活动记录查询格式进行 UNION 查询?
10 回答
CodeIgniter 的 ActiveRecord 不支持 UNION,因此您只需编写查询并使用 ActiveRecord 的查询方法。
$this->db->query('SELECT column_name(s) FROM table_name1 UNION SELECT column_name(s) FROM table_name2');
通过使用 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();
这是我曾经使用过的一种快速而肮脏的方法
// 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);
不是我最好的作品,但它解决了我的问题。
注意:我不需要订购结果。
您可以使用以下方法获取模型中的 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 变量中,而无需实际执行。
你很久以前就问过这个问题,所以也许你已经得到了答案。如果没有,这个过程可能会奏效。
通过修改 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`)
我找到了这个库,它非常适合我以 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 的开发版本,因为这是一个生产应用程序。)
这是我正在使用的解决方案:
$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);
试试这个
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();
}
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");
这是我创建的解决方案:
$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);