【问题标题】:How to show records from three tables without foreach如何在没有foreach的情况下显示三个表中的记录
【发布时间】:2016-09-21 17:36:54
【问题描述】:

我遇到了如何查询以连接 3 个表中的记录并在屏幕上打印结果的问题。我提出了解决方案,但不利于速度,我一直在寻求更好的解决方案。我的桌子是:

测试表

id_test
testName

问题表

id_quest
id_test
question

答案表

id_answer
id_quest
answer

每个测试有 7 个问题,每个问题有 10 个答案。

如何在不使用 foreach 的情况下编写数据库查询以在屏幕上列出这些记录?

我做了这样的解决方案:

    $this->db->select('id_test,testName,description,time,type,sum');
    $this->db->where('id_test',$idTest);
    $query['test'] = $this->db->get('tests')->result()[0];

    $this->db->select('id_quest,inquiry');
    $this->db->where('id_test',$idTest);
    $query['questions'] = $this->db->get('questions')->result();

    $i=0;
    foreach ($query['questions'] as $question) {
        $this->db->select('id_answer,response,value');
        $this->db->where('id_quest',$question->id_quest);
        $query['questions'][$i]->answer = $this->db->get('answer')->result();
        $i++;
    }
    return $query;

【问题讨论】:

  • 要么使用循环,要么为查询返回的内容写出循环中的每一行。
  • 所以不可能用我已经写过的另一种方式来写?
  • 是的,您可以使用 while,但必须使用循环。

标签: php mysql join


【解决方案1】:

您可以像这样进行更复杂的查询,这样您只需访问数据库一次:

SELECT 
t.id_test, t.testName, t.description, t.time, t.type, t.sum,
q.id_quest, q.inquiry,
a.id_answer, a.response, a.value
FROM tests AS t
LEFT JOIN questions AS q ON q.id_test = t.id_test
LEFT JOIN answers AS a ON a.id_quest = q.id_quest
WHERE t.id_test = $idTest;

那么您的代码将如下所示:

<?php
// your database info here
$db_host = '';
$db_user = '';
$db_pass = '';
$db_name = '';

$con = mysqli_connect($db_host,$db_user,$db_pass,$db_name);
if($con->connect_error)
    die('Connect Error (' . mysqli_connect_errno() . ') '. mysqli_connect_error());

$query = "SELECT 
t.id_test, t.testName, t.description, t.time, t.type, t.sum,
q.id_quest, q.inquiry,
a.id_answer, a.response, a.value
FROM tests AS t
LEFT JOIN questions AS q ON q.id_test = t.id_test
LEFT JOIN answers AS a ON a.id_quest = q.id_quest
WHERE t.id_test = ?";

if (!$stmt = $con->prepare($query))
    die('Prepare Error: ' . $con->error);

$idTest = 2;
if (!$stmt->bind_param('i', $idTest))
    die('Bind Parameters Error ' . $stmt->error);

if (!$stmt->execute())
    die('Select Query Error ' . $stmt->error);

while ($stmt->fetch())
{
// get each resulting answer row, complete with associated question id and test id
}
$stmt->close();
$con->close();

【讨论】:

    【解决方案2】:

    根据我从您的问题中得到的信息,您希望加入这些表格。我认为你应该能够做这样的事情:

    SELECT test_table.test_name,
           qestion_table.question, 
           answer_table.answers 
    FROM test_table
    INNER JOIN questions_table 
    on questions_table.id_test = test_table.id_test
    INNER JOIN answers_table
    ON answers_table.id_quest = questions_table.id_quest
    WHERE test_table.id_test = ?
    

    这应该将整个结果集作为一个对象返回,而不必多次查询数据库。

    【讨论】:

    • 如果要将结果作为简单数组处理或直接输出以维护分组,我还将按 test_name、问题、答案对输出进行排序。
    【解决方案3】:

    我会完全考虑使用 'where_in' 而不是向您的数据库抛出大量查询。

    即..

    //...
    
    $this->db->select('id_quest,inquiry'); 
    $this->db->where('id_test',$idTest);
    $query['questions'] = $this->db->get('questions')->result();
    
    $questionIds = array();
    
    foreach($query['questions'] as $question)
         $questionIds[] = $question->id_quest;
    
    $this->db->select('id_answer,response,value');
    $this->db->where_in('id_quest', $questionIds);
    $answers = $this->db->get('answer')->result();
    
    $i=0; // <<< Idk what the main purpose of this is, 
          //     but you do know you can simply use '[]' appending to an array, right?
    foreach ($answers as $answer) {
        $query['questions'][$i]->answer = $answer;
        $i++;
    }
    

    如果性能仍然是一个主要问题。查看缓存。 CodeIgniter 很好地支持了这一点。

    https://www.codeigniter.com/userguide3/libraries/caching.html

    P.S 还要查看 CI 中的 join 命令。 https://www.codeigniter.com/userguide2/database/active_record.html

    【讨论】:

    • 如果性能是一个问题,请不要使用 where_in - 这会在 db 优化器上强制使用特定的执行路径。如果您发现这可以加快查询速度,那么您可能还没有做家务。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-09-11
    • 2017-12-29
    • 2020-08-14
    • 1970-01-01
    • 2015-05-24
    相关资源
    最近更新 更多