用json将mysql foreach转换为单行

时间:2015-04-11 00:27:13

标签: php mysql json laravel

我需要一些帮助来循环遍历表并将行转换为新表中的单行。

表A包含100k +行。我想通过将值添加到json数组中来缩小表B中的内容。

表A具有以下结构:

+---------------+------------+------+-----+---------+----------------+
| Field         | Type       | Null | Key | Default | Extra          |
+---------------+------------+------+-----+---------+----------------+
| id            | int(11)    | NO   | PRI | NULL    | auto_increment |
| result_id     | int(11)    | NO   |     | 0       |                |
| question_id   | int(11)    | NO   |     | 0       |                |
| question_type | tinyint(4) | NO   |     | 0       |                |
| answer        | tinytext   | NO   |     | NULL    |                |
| user_answer   | tinytext   | NO   |     | NULL    |                |
| exam_id       | int(11)    | NO   |     | NULL    |                |
+---------------+------------+------+-----+---------+----------------+

表B具有以下结构:

+------------+-----------+------+-----+-------------------+-----------------------------+
| Field      | Type      | Null | Key | Default           | Extra                       |
+------------+-----------+------+-----+-------------------+-----------------------------+
| id         | int(11)   | NO   | PRI | NULL              | auto_increment              |
| exam_id    | int(11)   | NO   |     | NULL              |                             |
| score      | int(11)   | NO   |     | NULL              |                             |
| exam_data  | text      | NO   |     | NULL              |                             |
| created_at | timestamp | NO   |     | CURRENT_TIMESTAMP | on update CURRENT_TIMESTAMP |
| updated_at | timestamp | YES  |     | NULL              |                             |
| deleted_at | timestamp | YES  |     | NULL              |                             |
+------------+-----------+------+-----+-------------------+-----------------------------+

实际上,我想循环遍历表A中的所有行,并将具有相同result_id的行添加到数组中。我想接着这个数组并在表B中插入一个新行。

这是我迄今为止所拥有的,但它无法正常运作。

$array = array();
$id = null;

TableA::chunk(100, function($answers)
{
    foreach($answers as $old)
    {
        $id = $old->result_id;

        if($id == $old->result_id)
        {
            $array[] = array("type" => $old->question_type, "answer" => $old->user_answer);
        }
    }

    $new = new TableB;
    $new->exam_id = $id;
    $new->exam_data = json_encode($array);
    $new->save();
});

我想利用Laravel chunk函数来避免SQL服务器超时。

有人能指出我正确的方向吗?

2 个答案:

答案 0 :(得分:1)

我讨厌ORM采取与简单CRUD操作不同的操作。所以我将用简单的SQL /伪代码描述一个想法。

  1. SELECT DISTINCT result_id FROM TableA; //选择唯一的result_ids
  2. 在PHP中循环遍历result_ids,并为每个result_id执行:
    1. SELECT * FROM TableA WHERE result_id = $ row [' result_id']; //选择具有指定result_id的所有行
    2. 循环结果,创建新的TableB对象,并将其保存到db。
  3. 此外,为了节省内存,您可以在循环外部创建对象TableB,然后在循环中创建对象TableB以更改所需的字段。通过这种方式,您可以节省每次迭代创建新对象所需的内存和时间。

    P.S。 为了更有效的方式,我会使用纯SQL查询。此外,最好动态创建查询,以便能够分批向db插入数据,而不是为每行执行INSERT。

    我的意思是,首先构建包含多个插入的查询,然后通过只运行一个查询来插入它:

    INSERT INTO Table ( Column1, Column2 ) VALUES
    ( Value1, Value2 ), ( Value1, Value2 )
    

答案 1 :(得分:1)

我建议做一个SELECT,循环结果并使用result_id创建数组的第一个维度。然后使用question_id创建数组的第二个维度。

$aJsonResults = array();

foreach($aDatabaseResults as $key => $value){
     $aJsonResults[$value['result_id']][$value['question_id']] = $value['answer'];
}

然后循环遍历第一级$aJsonResultsjson_encode值。

$aJsonedResults = array()
foreach($aJsonResults as $key => $value){
    $aJsonedResults[$key] = json_encode($value);
}

然后创建你的插入@ alexander-ravikovich的建议。