Requête de L'UNION avec le modèle d'enregistrement actif de codeigniter

Comment faire une requête UNION avec le format de requête active record de PHP CodeIgniter framework?

26
demandé sur Somnath Muluk 2010-01-11 11:37:03

10 réponses

ActiveRecord de CodeIgniter ne supporte pas L'UNION, donc vous n'avez qu'à écrire votre requête et utiliser la méthode de requête ActiveRecord.

$this->db->query('SELECT column_name(s) FROM table_name1 UNION SELECT column_name(s) FROM table_name2');
31
répondu Zack 2010-01-11 20:39:29

C'est un moyen rapide et sale méthode une fois, j'ai utilisé

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

pas mon meilleur travail, mais il a résolu mon problème.

note: je n'ai pas besoin de commander le résultat.

22
répondu afinno 2012-12-17 02:16:15

en faisant union en utilisant last_query (), cela peut nuire à la performance de l'application. Parce que pour une seule union il faudrait exécuter 3 requêtes. j'.e pour le "n" de l'union "n+1" requêtes. Cela n'affectera pas beaucoup pour 1-2 query union. Mais cela posera problème si l'union de plusieurs requêtes ou tableaux ayant de grandes données.

ce lien vous aidera beaucoup:enregistrement actif sous-requêtes

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();
18
répondu Somnath Muluk 2011-12-13 07:22:44

Vous pouvez utiliser la méthode suivante pour obtenir la déclaration SQL dans le model:

$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, donc peut-être avez-vous déjà la réponse. si pas, ce processus peut faire l'affaire.

8
répondu Souvik 2011-06-27 15:28:15

en modifiant la réponse de somnath huluks, j'ajoute ces 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 virtuellement utiliser des unions sans liens de dépendance avec db_driver.

pour utiliser union avec cette méthode, il vous suffit de faire des requêtes active record régulières, mais en appelant union_push au lieu de get.

note: vous devez vous assurer que vos requêtes ont des colonnes correspondantes comme régulière les syndicats

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

donnerait:

(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`)
3
répondu am05mhz 2013-02-02 03:02:02

j'ai trouvé cette bibliothèque, qui a bien fonctionné pour moi d'ajouter UNION dans un style ActiveRecord:

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

MAIS j'ai eu à prendre la get_compiled_select() méthode de la branche dev de CodeIgniter d'abord (disponible ici: https://github.com/EllisLab/CodeIgniter/blob/develop/system/database/DB_query_builder.php -- DB_query_builder remplacera DB_active_rec). Probablement cette méthode sera disponible dans une future production de CodeIgniter.

Une fois que J'ai ajouté cette méthode à DB_active_rec.php dans le système / base de données 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.)

2
répondu Matt Browne 2013-01-11 00:58:41

essayer celui-ci

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();
}
1
répondu Ameen Maheen 2015-07-13 07:37:27

Voici 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);
1
répondu Levan Abashidze 2017-01-26 22:26:11

la réponse de bwisn est meilleure que toutes les autres et fonctionnera mais pas très bien en performance car elle exécutera les requêtes secondaires en premier. get_compiled_select n'exécute pas la requête; il la compile pour l'exécuter plus tard donc est 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");
0
répondu Dilpazir Ahmad 2018-09-27 10:00:48

Voici une solution que j'ai créée:

$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);
-1
répondu bwisn 2011-03-24 21:07:34