Codeigniter 3.0 查询错误

Posted

技术标签:

【中文标题】Codeigniter 3.0 查询错误【英文标题】:Codeigniter 3.0 query bug 【发布时间】:2016-05-01 01:43:28 【问题描述】:

复制此表:User_Posts

ID     | Upvotes | Downvotes | CAT  |
___________________________________
42134  |   5     |      3    | Blogs|
------------------------------------
12342  |   7     |      1    | Blogs|
-------------------------------------
19344  |   6     |      2    | Blogs|
------------------------------------

我需要获取某个项目在其类别中的排名。因此 ID:19344 排名第 2,获得 4 次支持,排在 12342 之后,获得 6 次支持。排名由其类别中的(赞成-反对)计数确定。

所以我写了这个 mysql 查询。

SELECT rank FROM (SELECT *, @rownum:=@rownum + 1 AS rank
FROM User_Posts where CAT= 'Blogs' order by 
(Upvotes-Downvotes) DESC) d, 
(SELECT @rownum:=0) t2 WHERE POST_ID = '19344'

直接在mysql中运行时返回我(Rank = 2)。这是正确的结果

但是,当我尝试通过 code-igniter 的查询构建器构建它时,我得到了

$table = 'User_Posts'; 
$CAT= 'Blogs'; 
$POST_ID = '19344';

 $sql = "SELECT rank FROM (SELECT *, @rownum:=@rownum + 1 AS
 rank FROM $table where CAT= ? 
 order by (Upvotes-Downvotes) DESC) d, 
(SELECT @rownum:=0) t2 WHERE POST_ID= ?";

$query= $this->db->query($sql, array($CAT,$POST_ID))->row_array();

返回一个空结果:array(rank=>);

那么我的问题是...... 但是为什么

我也将接受一个答案,即从 code-igniters 查询生成器运行此查询的另一种方法,但理想情况下,我想知道为什么这个东西坏了。

【问题讨论】:

您不能将 SQL 简化为 SELECT (Upvotes - Downvotes) AS rank FROM User_Posts WHERE CAT = 'Blogs' AND POST_ID = 19344; 吗?似乎这在 CI 的查询构建器中也很容易实现。 @quickshiftin rank 不是(upvotes-downvotes)的数量,而是该项目相对于同一类别中其他项目的位置。 好的,你如何解释给定类别的(upvotes-downvotes)关系? @quickshiftin 好问题,现在它只是相同的排名 我可能会结合使用查询日志和调试器来跟踪它。另一种选择是查看代码点火器可以使用的替代查询。也许它不喜欢你当前查询中的变量赋值。 【参考方案1】:

过去我也遇到过类似的问题,结果我必须先用单独的查询初始化变量,我不确定是否仍然如此,但还是试试看吧。

//initialize the variable, before running the ranking query.
$this->db->query('SELECT 0 INTO @rownum');
$query= $this->db->query($sql, array($CAT,$POST_ID))->row_array();

【讨论】:

这是您必须初始化变量的解决方案。非常感谢。 @Edward ...但你已经知道了!您只是在查询中的错误位置执行了此操作。注:如果你这样做,你可以从你的查询中删除, (SELECT @rownum:=0) t2【参考方案2】:

我不知道为什么您的代码不起作用。我写了另一个解决方案,它会起作用。试试下面的代码。

$select="FIND_IN_SET( (upvote-downvote), (SELECT GROUP_CONCAT( (upvote-downvote) ORDER BY (upvote-downvote) DESC ) as total FROM (User_Posts))) as rank";
$this->db->select($select,FALSE);
$this->db->from('(User_Posts)',FALSE);
$this->db->where('ID',19344);
$this->db->where('CAT','Blogs');
$query = $this->db->get();

【讨论】:

【参考方案3】:

编写一个存储函数来进行查询。然后让 Codeigniter 只做

query("SELECT PostRank(?,?)", $CAT, $POST_ID);

限制:由于您不能在存储函数中执行PREPARE,因此该函数必须特定于一个表User_Posts

【讨论】:

【参考方案4】:

我不完全确定这是否是问题所在,但我会在子查询中初始化 @rownum

SELECT rank 
  FROM (
     SELECT *, 
            @rownum:=@rownum + 1 AS rank 
       FROM $table
       JOIN (SELECT @rownum := 0) init
      WHERE CAT= ? 
   ORDER BY (Upvotes-Downvotes) DESC
       ) d 
 WHERE post_id = ?

否则我会担心 @rownum 未定义 (NULL) 并在计算 rank (NULL + 1 = NULL) 时保持这种状态,之后只会分配 0 的值。因此rank 返回为NULL,你得到['rank'=>]

在恒定连接中(直接在 MySQL 中)再次运行它会得到正确的结果,因为 @rownum 将从上一个查询中的值 0 开始,而 rank 将被正确计算。

我猜 codeigniter 每次运行查询时都会启动一个新的连接/事务,@rownum 每次都从NULL 开始,给出['rank'=>]

【讨论】:

以上是关于Codeigniter 3.0 查询错误的主要内容,如果未能解决你的问题,请参考以下文章

Codeigniter 3.0 会话表名称为空字符串,因此出现错误

codeigniter,从不直接调用视图,有人可以解释一下

codeigniter 4 设置会话变量 $session = \Config\Services::session();全球

要使用codeigniter框架还是标准的php? [关闭]

使用 Codeigniter 进行数据表服务器端处理

Codeigniter:ORDER BY CASE 查询中的错误