Comment faire une requête UNION avec le format de requête d'enregistrement actif du framework [CodeIgniter] de PHP?
ActiveRecord de CodeIgniter ne supporte pas UNION, vous pouvez donc écrire votre requête et utiliser la méthode de requête d'ActiveRecord.
$this->db->query('SELECT column_name(s) FROM table_name1 UNION SELECT column_name(s) FROM table_name2');
Ceci est une méthode rapide et sale que j'ai utilisé une fois
// 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);
Ce n’est pas mon meilleur travail, mais cela a résolu mon problème.
note: je n'ai pas eu besoin de commander le résultat.
En faisant l'union avec last_query (), cela peut entraver les performances de l'application. Parce que pour une union unique, il faudrait exécuter 3 requêtes. c'est-à-dire pour "n" union "n + 1" requêtes. Cela n'affectera pas beaucoup l'union d'une ou deux requêtes. Mais cela posera problème si l’union de nombreuses requêtes ou tables ayant des données volumineuses.
Ce lien vous aidera beaucoup: sous-requêtes d'enregistrement actives
Nous pouvons combiner l'enregistrement actif avec des requêtes manuelles. Exemple:
// #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();
Vous pouvez utiliser la méthode suivante pour obtenir l’instruction SQL dans le modèle:
$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();
De cette façon, l'instruction SQL sera dans la variable $ subquery, sans l'exécuter réellement.
Vous avez posé cette question il y a longtemps, alors peut-être avez-vous déjà la réponse. sinon, ce processus peut faire l'affaire.
en modifiant somnath huluks answer, j’ajoute les variables et fonctions suivantes à la classe DB_Active_rec comme suit:
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;
}
}
par conséquent, vous pouvez utiliser virtuellement des unions sans dépendances à db_driver.
pour utiliser union avec cette méthode, vous devez simplement effectuer des requêtes d'enregistrement actives régulières, mais en appelant union_Push au lieu de get.
remarque: vous devez vous assurer que vos requêtes ont des colonnes identiques à celles des unions régulières
exemple:
$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();
produirait:
(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`)
J'ai trouvé cette bibliothèque, qui m'a bien aidé à ajouter UNION dans un style ActiveRecord:
https://github.com/NTICompass/CodeIgniter-Subqueries
MAIS je devais d'abord récupérer la méthode get_compiled_select()
de la branche dev de CodeIgniter (disponible ici: https://github.com/EllisLab/CodeIgniter/blob/develop/système/database/DB_query_builder.php - DB_query_builder remplacera DB_active_rec). Vraisemblablement, cette méthode sera disponible dans une future version de production de CodeIgniter.
Une fois que j'ai ajouté cette méthode à DB_active_rec.php dans system/database, cela a fonctionné comme un charme. (Je ne voulais pas utiliser la version dev de CodeIgniter car il s'agit d'une application de production.)
essaye celui-là
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();
}
C'est la solution que j'utilise:
$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);
la réponse de bwisn est meilleure que tout et fonctionnera, mais sa performance ne sera pas satisfaisante car elle exécutera d'abord les sous-requêtes. get_compiled_select n’exécute pas la requête; il se contente de le compiler pour une exécution ultérieure, il est donc plus rapide essayez celui-ci
$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");