将带有嵌套子查询的原始 SQL 转换为 CodeIgniter 查询构建器方法

问题描述 投票:0回答:2

正在寻找一些帮助,但发现了一些帮助,但当 FROM 也是子查询时却一无所获。

SELECT COUNT(*) 
  FROM 
    ( SELECT tc.*, 
             ( SELECT status FROM test_case_executions tce 
                   WHERE tce.test_case_id = tc.id 
                   ORDER BY tce.execution_date DESC, tce.id DESC LIMIT 1 
             ) AS last_status FROM test_cases tc 
    ) a 
WHERE a.last_status = '$status'

CI 有没有办法只使用它并执行它,或者有人可以帮助我按照 CI 想要的方式编写它?

php mysql codeigniter subquery query-builder
2个回答
1
投票

您需要的一切都可以在这里找到,正如上面评论中提到的。为了帮助您入门,您可以这样做:

$this->db->query("
SELECT COUNT(*) AS amount
FROM (  SELECT tc.*,
        (   SELECT status
            FROM test_case_executions AS tce 
            WHERE tce.test_case_id = tc.id 
            ORDER BY tce.execution_date DESC, tce.id DESC
            LIMIT 1) AS last_status
        FROM test_cases AS tc 
    ) AS a 
WHERE a.last_status = ?
", array($status));

基本上评论都是这么说的。是什么让这比简单的

mysql_query
等更“CI 方便”,是因为你可以转义传递的值以摆脱错误和 sql 注入。请注意最后一部分
?
和第二个参数
array($status)
。我还设计了这个查询的样式,使其更容易被眼睛看到(imo)。

您可能会想“但是我想使用 Active Records!D:”,但是更高级的东西需要您离开舒适区。祝你好运!


0
投票

我不同意@Anusha的观点,即构建这个嵌套查询结构是“复杂的”。 只需使用查询生成器方法从最里面的子查询构建出来,然后根据需要将构建的查询插入到其父查询中。

我建议调整 SQL 以避免 SELECT 子句中的子查询,而不仅仅是将发布的 SQL 转换为查询构建器调用,而这些子查询往往性能不佳。

我建议加入一个子查询,该子查询按 id 对测试用例进行分组并返回最新的执行日期,然后将执行表加入到该派生表中,以便能够访问每个测试用例的last_status,按传入的状态过滤它们,并计算总计。

public function countTestCasesByStatus(string $status): int
{
    $latestExecutionPerId = $this->db
        ->select('tc.id, MAX(tce.execution_date) last_execution_date')
        ->join('test_case_executions tce1', 'tc.id = tce.test_case_id')
        ->group_by('tc.id')
        ->get_compiled_select('test_cases tc');

    return $this->db
        ->join('test_case_executions tce2', 'lepi.id = tce2.test_case_id AND lepi.last_execution_date = tce2.execution_date')
        ->where('tce2.status', $status)
        ->count_all_results("($latestExecutionPerId) lepi");
}

渲染的 SQL(假设输入字符串为

foo
):

SELECT COUNT(*) AS `numrows`
FROM (
    SELECT `tc`.`id`, MAX(tce.execution_date) last_execution_date
    FROM `test_cases` `tc`
    JOIN `test_case_executions` `tce1` ON `tc`.`id` = `tce`.`test_case_id`
    GROUP BY `tc`.`id`
) lepi
JOIN `test_case_executions` `tce2` ON `lepi`.`id` = `tce2`.`test_case_id` AND `lepi`.`last_execution_date` = `tce2`.`execution_date`
WHERE `tce2`.`status` = 'foo'
© www.soinside.com 2019 - 2024. All rights reserved.