在codeigniter中转换复杂的JOIN查询

时间:2013-04-19 15:06:58

标签: php mysql sql codeigniter-2

我正在将我现有的网站转换为CI,并且我已经尝试了几天将此查询转换为CI友好代码:

$result = mysql_query("
    SELECT t1.mnumber, t1.mcontent, t1.mcontact
    FROM sms t1
    JOIN (
        SELECT mContent,mcontact, mnumber, MAX(mID) mID
        FROM sms
        GROUP BY mContact
    ) t2 ON t1.mcontact = t2.mcontact AND t1.mid = t2.mid
    GROUP BY t1.mContact
    ORDER BY t1.mid DESC
"); 

但无论我尝试什么,我都无法在CI上得到正确的结果。

我希望你们能在这里帮助我!


最接近我得到的结果,是当我使用子查询黑客时。 然而,出于挫败感,我删除了代码块并继续尝试。

我决定使用平面查询,就像上面发布的那样。这几乎给了我结果。

$query = $this->db->query("SELECT t1.mnumber, t1.mcontent, t1.mcontact FROM sms t1
JOIN (SELECT mContent,mcontact, mnumber, MAX(mID) mID FROM sms GROUP BY mContact) t2
ON t1.mcontact = t2.mcontact AND t1.mid = t2.mid GROUP BY t1.mContact ORDER BY t1.mid DESC"); 


$contacts = array();

//Add data to our array
foreach($query->result() as $row){
     echo $row->mNumber;
}

return $contacts;

但是,在我看来,我收到通知“消息:未定义的属性:stdClass :: $ mNumber”

所以仍然没有结果,加上我更喜欢CI查询方法。

4 个答案:

答案 0 :(得分:5)

你可以在像这样的codeigniter中使用它

$query = "  SELECT t1.mnumber, t1.mcontent, t1.mcontact
            FROM sms t1
            JOIN (
                SELECT mContent,mcontact, mnumber, MAX(mID) mID
                FROM sms
                GROUP BY mContact
            ) t2 ON t1.mcontact = t2.mcontact AND t1.mid = t2.mid
            GROUP BY t1.mContact
            ORDER BY t1.mid DESC"; 
$result =   $this->db->query($query);           
return $result->result();

第二种方法

您可以使用codeigniter的子查询方式为此目的执行此操作 将不得不破解codeigniter。像这样。转到system / database / DB_active_rec.php 从这些函数中删除public或protected关键字

public function _compile_select($select_override = FALSE)
public function _reset_select()

现在子查询写入可用现在这里是带有活动记录的查询

$select =   array(
                'mContent',
                'mcontact',
                'mnumber',
                'MAX(mID) mID'
            );
$this->db->select($select);
$this->db->from('sms');
$this->db->group_by('mContact');
$subquery = $this->db->_compile_select(); // get the query string

$this->db->_reset_select(); // reset so it can newly form the query

unset($select);
$select =   array(
                't1.mnumber',
                't1.mcontent',
                't1.mcontact'
            );
$this->db->select($select);
$this->db->join('',"($subquery)");
$this->db->from('sms t1');
$this->db->group_by('t1.mContact');
$this->db->order_by('t1.mid','DESC');
$result =   $this->db->get();
return $result->result();

事情已经完成了。干杯!!! 注意:使用子查询时,必须使用

$this->db->from('myTable')

而不是

$this->db->get('myTable')

运行查询。

答案 1 :(得分:0)

呃,不应该(猜测)......

 SELECT t1.mnumber
      , t1.mcontent
      , t1.mcontact
      , t1.mid
   FROM sms t1
   JOIN 
      ( SELECT mcontact
             , MAX(mID) mID 
          FROM sms 
         GROUP BY mContact
      ) t2
     ON t1.mcontact = t2.mcontact 
    AND t1.mid = t2.mid 
  ORDER 
     BY t1.mid DESC;

答案 2 :(得分:0)

这可能无法完全回答您的问题,但对于那些使用Google搜索"JOIN AND"的人(以便AND可以Join {em>} {em}在 WHERE条款开始之前),这是一个hacky方式:

$this->db->join('table_to_join', 'first_table.connect_id = table_to_join.id AND table_to_join.some_filter != 0');

绝对不是很漂亮,但这显然会迫使ANDJOIN之后立即发生,然后才能进入WHERE内容以查询first_table的其余查询}

答案 3 :(得分:0)

嗯,它很容易在CI版本3 +

中实现
$subQuery = $this->db->select( 'table2.*' )
  ->join( 'table3', 'table3.orderId = table2.fkOrderId', 'INNER' )
  ->where()->get_compiled_select( 'table2' );

$this->db->select( 'table1.*' )
  ->join( '(' . $subQuery . ') AS b', 'b.`fkCouponId` = table1.couponId', 'LEFT', FALSE )
  ->get( 'table1' )

提示:确保不要在子查询部分上方使用任何查询构建器方法。