【问题标题】:PHP - How to create multidimentional JSON from MySQL?PHP - 如何从 MySQL 创建多维 JSON?
【发布时间】:2017-06-18 18:24:47
【问题描述】:

我需要从两个 MySQL 表创建一个多维 JSON。我的代码有效,但我认为它写得非常糟糕,因为它首先连接 DB 值,然后在 PHP 中分解结果字符串。必须有更好(更快)的方法来做到这一点。

我知道类似的问题已经被问过很多次,但我是个菜鸟,我不知道如何将答案应用到我的案例中。

所以,我有以下 MySQL 表:

    tbl1
-----------------------------
id| question   |correctanswer
-----------------------------
 1|'Yes or no?'|    'Yes'
 2|   'Who?'   |    'Peter'

    tbl2
-----------------------------
id|questionid| answeroptions
-----------------------------
1 |         1|'Yes'
2 |         1|'No'
3 |         2|'Peter'
4 |         2|'John'
5 |         2|'James'
6 |         2|'Jack'

我想构建这样的 JSON 字符串:

{
    "id":"1",
    "question":"Yes or no?",
    "correct_answer":"Yes",
    "answeroptions":[
                    "Yes",
                    "No"
                    ]
}
{
    "id":"2",
    "question":"Who?",
    "correct_answer":"Peter",
    "answeroptions":[
                    "Peter",
                    "John",
                    "James",
                    "Jack"
                    ]
}

这是我的代码:

$sql = "SELECT tabl1.id, tabl1.question, tabl1.correctanswer, 
    GROUP_CONCAT(DISTINCT tbl2.answeroptions)
    FROM tabl1
    LEFT JOIN tbl2 ON (tabl1.id = tbl2.questionid)
    GROUP BY tabl1.id;";

$jsonarray = array();
$result = $conn->query($sql);
$i = 0;

while ($row = mysqli_fetch_array($result, MYSQL_NUM)) {
    $jsonarray[$i]["topic"] = $row[0];
    $jsonarray[$i]["id"]=$row[1];
    $jsonarray[$i]["question"]=$row[2];
    $jsonarray[$i]["correct_answer"]=$row[3];
    $jsonarray[$i]["answeroptions"] = array();
    $jsonarray[$i]["answeroptions"] = explode(",",$row[4]);
    $i++;
}

for ($d=0; $d<count($jsonarray);$d++){
    echo json_encode($jsonarray[$d])."<br>";
}

更新: 我对三个用例进行了性能测试:

  1. 布莱克的建议
  2. ded 的建议
  3. 将 answeroptions 合并到 tbl1 中的新列中以消除第二个请求,并使用 ded 的脚本进行了相应修改。

我用了一个 for 循环 * 100 次,结果如下:

  1. 0.16780591011047 秒
  2. 0.0067291259765625 秒
  3. 0.0005500316619873 秒

因此,基于性能,我得出结论,在 DB 中使用一对多关系并不总是最佳选择。对于这样简单的任务,所有数据都可以存储在同一个表中。

谢谢大家的帮助!

【问题讨论】:

  • 我认为您只需要在代码末尾删除您的 for 循环即可。有echo json_encode($jsonarray[$d]);就行了,别循环了
  • @bassxzero 感谢您的建议!仅针对可能也对此进行研究的其他人:我需要删除 [$d],它起作用了:json_encode($jsonarray);.
  • 没注意到 d,但是它需要去

标签: php mysql json multidimensional-array one-to-many


【解决方案1】:
$sql = "SELECT tabl1.id, tabl1.question, tabl1.correctanswer,
GROUP_CONCAT(DISTINCT tbl2.answeroptions)
FROM tabl1
LEFT JOIN tbl2 ON (tabl1.id = tbl2.questionid)
GROUP BY tabl1.id;";

$result = $conn->query($sql);
$jsonarray = mysqli_fetch_all($result, MYSQLI_ASSOC);

foreach ($jsonarray as $row) {
    $row["answeroptions"] = explode(",", $row["answeroptions"]);
}

echo json_encode($jsonarray)."<br>";

【讨论】:

    【解决方案2】:

    您确实应该进行两次查询以获得最佳性能。试试这个代码(未经测试)

    # Question array holder
    $questions = [];
    
    
    # Loading the questions
    $query = "  SELECT
                    `id`,
                    `question`,
                    `correctanswer`
                FROM
                    `tabl1`";
    $result = mysqli_query( $conn, $query );
    
    
    # Nothing to send
    if( mysqli_num_rows( $result ) == 0 ) {
        exit( '[]' );
    }
    
    
    # Adding questions to array
    while( $question_data = mysqli_fetch_assoc( $result ) ) {
        $question_data[ 'answeroptions' ] = [];
        $questions[ $question_data[ 'id' ] ] = $question_data;
    }
    
    
    # Loading the answer
    $query = "  SELECT
                    *
                FROM
                    `tabl2`
                WHERE
                    `questionid` IN (" . implode( ',', array_keys( $questions ) ) . ")";
    $result = mysqli_query( $conn, $query );
    
    
    # Adding answers to array
    while( $answer_id = mysqli_fetch_assoc( $result ) ) {
        $questions[ $answer_id[ 'questionid' ] ][ 'answeroptions' ][] = $answer_id[ 'answeroptions' ];
    }
    
    
    # Sending the questions
    echo json_encode( array_values( $questions ) );
    

    【讨论】:

    • 谢谢@blake-a-nichols,这行得通!这是否意味着无法使用一个 SQL 查询来达到相同的结果?
    • 我不知道。这两种查询方法总是更快,因为您可以正确地索引您的表,并且您限制了 mysql 必须做的工作来获取您的数据。
    • @blake-a-nichols 如果我删除第二个表并将所有 answeroptions 移动到 tbl1 怎么办?我可以创建一个包含逗号分隔字符串的 varchar 列,然后将它们分解为一个数组。它会比执行两个查询更快吗?将有 2 到 5 个选项,而不是更多。 (对我来说管理问题肯定会更容易,因为我自己在 Excel 中编写它们。)[编辑:语法]
    • 我会将它们保存在单独的表中,这是关系数据库的主要目的。此外,如果您决定在“错误”答案中添加一些随机性,或者如果您创建管理页面来添加/编辑问题和答案,那么它可以在未来为您提供灵活性,那么您可以通过 id 引用所有内容。
    • 听起来不错,但我认为我仍然可以在将所有数据存储在一个表中的同时做到这一点。然而,消除第二个请求会带来巨大的性能提升,请参阅我对帖子的更新。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-10-14
    • 2021-12-23
    • 1970-01-01
    • 2016-12-07
    • 1970-01-01
    • 1970-01-01
    • 2017-04-04
    相关资源
    最近更新 更多